Back to notes
mastery-data-sql
Featured

Advanced SQL Indexing: เจาะลึกกลยุทธ์รีดประสิทธิภาพ Database

Index ไม่ใช่แค่ใส่ B-Tree มั่วๆ แล้วจะเร็ว! รู้จัก Composite Index, Covering Index และวิธีใช้ EXPLAIN ANALYZE เพื่อแก้ปัญหาระบบอืดแบบมืออาชีพ

January 30, 20262 min read readNNexis by Seereen

ลองนึกถึงวันที่คุณสร้าง Index ไปแล้ว แต่ Query ก็ยังช้าเหมือนเดิม:

HLJS SQL
-- ❌ สถานการณ์: มี Index (firstname) และ Index (lastname) แยกกัน
SELECT * FROM users WHERE firstname = 'John' AND lastname = 'Doe';
-- 🌋 พัง! Database มักจะเลือกใช้แค่ Index ตัวเดียว แล้วมานั่งไล่หาตัวที่เหลือทีละแถว (Low Selectivity)
-- ทำให้ประสิทธิภาพไม่ได้เพิ่มขึ้นอย่างที่ควรจะเป็น

ปัญหา: การสร้าง Index แบบสุ่มสี่สุ่มห้าโดยไม่เข้าใจพฤติกรรมการ Query ของแอปพลิเคชัน คือการเสีย Resource ไปฟรีๆ โดยไม่ได้ความเร็วกลับมา Senior ต้องเข้าใจว่า "ลำดับ" และ "ประเภท" ของ Index คือตัวตัดสินความเป็นความตายของ Performance ครับ


💡 2. Real-Life Analogy: ตู้ดัชนีบัตรห้องสมุด vs รายชื่อเบอร์โทร

  • Composite Index (Index รวม): เหมือนการหาหนังสือในห้องสมุดที่แยกหมวดหมู่เป็น [หมวด -> ชื่อผู้แต่ง -> ชื่อเรื่อง]. ถ้าคุณรู้หมวดและชื่อผู้แต่ง คุณจะเจอหนังสือทันที แต่ถ้าคุณรู้แค่ชื่อเรื่อง (ตัวสุดท้าย) คุณจะต้องไล่หาทั้งตู้!
  • Covering Index (ตั๋วทางด่วน): เหมือนการที่คุณมี "เมนูสั้นๆ หน้าร้าน" ที่บอกทั้งชื่ออาหารและราคา. คุณไม่ต้องเดินเข้าไปดูเมนูเล่มใหญ่ในร้าน (Table Heap) คุณตัดสินใจได้ทันทีจากข้อมูลหน้าร้านเลย
  • GIN Index: เหมือน "ดัชนีท้ายเล่มหนังสือ". ที่บอกว่าคำว่า "Database" อยู่หน้าไหนบ้าง (เหมาะกับข้อมูลที่เป็น Array หรือ JSON)

🚀 3. Execution Journey: มหากาพย์ EXPLAIN ANALYZE

ก่อนจะฟันธงว่าระบบช้าตรงไหน Senior จะใช้คำสั่ง "เปิดตาทิพย์"

🛠 Step-by-step:

  1. The Investigation: รัน EXPLAIN ANALYZE นำหน้า Query ที่สงสัย
  2. The Result (Reading Plan):
    • Seq Scan: หายนะ! มันกำลังอ่านทั้งตาราง (ต้องแก้)
    • Index Scan: ดี มันใช้สารบัญ
    • Index Only Scan: ⚡⚡ สุดยอด! มันได้ข้อมูลครบจากสารบัญโดยไม่ต้องไปเปิดตารางจริง
  3. The Optimization: ปรับปรุง Composite Index ให้เรียงลำดับคอลัมน์จาก "ตัวที่กรองได้เยอะที่สุด" ไว้ซ้ายสุด (Left-most prefix rule)
HLJS SQL
// ✅ Best Practice: สร้าง Composite Index เพื่อการค้นหาหลายเงื่อนไข
CREATE INDEX idx_full_name ON users (firstname, lastname);
// 🛠 จำไว้: Index นี้ใช้หา (firstname) ได้ แต่ใช้หาเฉพาะ (lastname) 'ไม่ได้'!

🪤 4. The Junior Trap: โรค "Over-Indexing"

จูเนียร์มักจะใส่ Index ให้กับคอลัมน์ที่มีค่าซ้ำกันเยอะๆ (Low Cardinality):

HLJS SQL
-- ❌ Junior Trap: สร้าง Index บนคอลัมน์ 'gender' หรือ 'is_active'
CREATE INDEX idx_gender ON users (gender);
-- 🌋 พัง! Database จะมองว่า "การอ่านสารบัญที่มีคนเป็นล้านแต่มีแค่ 2 ค่า (ชาย/หญิง)
-- นั้นเสียเวลากว่าการอ่านทั้งตารางตรงๆ" สุดท้าย Index นี้จะถูกเมินและเสียพื้นที่ฟรีๆ

ระวัง: อย่า Index ข้อมูลที่ "ไม่ช่วยคัดกรอง" (เช่น ข้อมูลที่มีแค่ True/False) ✅ การแก้ไข: Index เฉพาะคอลัมน์ที่ค่ามีความหลากหลายสูง (Unique/High Cardinality) เท่านั้น


⚖️ 5. The Why Matrix: B-Tree vs GIN vs Hash

ประเภท Indexจุดเด่น (Pro)จุดด้อย (Con)เหมาะกับสถานการณ์
B-Tree (มาตรฐาน)⚡⚡⚡ เร็ว, รองรับ Range (> <)ขนาดใหญ่ตามข้อมูลงานทั่วไป 90% ของโลก
GIN (Inverted)🚀 เทพสำหรับอาเรย์และ JSONเขียนข้อมูลช้ามากFull Text Search / JSONB
Covering Index⚡⚡⚡ เร็วที่สุด (No Heap access)ต้องเก็บข้อมูลซ้ำซ้อนQuery ที่ขอข้อมูลเดิมซ้ำๆ

🎓 6. Senior Mindset Summary

การเป็น Senior คือการมองว่า "Index ไม่ใช่ยาวิเศษ แต่มันคือโครงสร้างข้อมูลที่ต้องมีการวางแผน". การเขียน SQL ที่มีประสิทธิภาพเริ่มต้นที่การเข้าใจว่า Database ของคุณมี 'สมุดสารบัญ' หน้าตาเป็นอย่างไรครับ!

Share this note

© 2026 My Notes by Seereen