0Pricing
SQL Interview Prep · บทเรียน

ดัชนีครอบคลุมและการสแกนเฉพาะดัชนี

เพิ่มคอลัมน์ที่จำเป็นเพื่อให้คำสั่งค้นหาไม่ต้องเข้าถึงตารางหลัก

ดัชนีครอบคลุมและการสแกนเฉพาะดัชนี เป็นบทเรียน SQL Interview Prep ฟรีบน CoddyKit นี่คือบทเรียนที่ 3 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน SQL Interview Prep และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส SQL Interview Prep มีบทเรียนทั้งหมด 4 บทเรียน

การนึกย้อนถึงการดึงข้อมูลจากฮีป

ก่อนหน้านี้คุณได้เรียนรู้ว่า บีทรีทั่วไปจะเก็บเฉพาะคอลัมน์ที่ทำดัชนีและตัวชี้แถว ดังนั้นหลังจากดัชนีค้นหาแถวที่ตรงกันแล้ว กลไกฐานข้อมูลยังต้องไปที่ตารางเพื่ออ่านคอลัมน์อื่น การไปอ่านตารางต่อนี้คือ การดึงข้อมูลจากฮีป และเป็นต้นทุนที่ ดัชนีครอบคลุมถูกออกแบบมาเพื่อกำจัด

ผู้สัมภาษณ์ถามเรื่องดัชนีครอบคลุมเพื่อดูว่าคุณเข้าใจหรือไม่ว่า เหตุใดดัชนีจึงสามารถตอบคำสั่งค้นหาได้ทั้งหมดโดยไม่ต้องเข้าถึงตาราง

ความหมายของคำว่า ‘ครอบคลุม’

ดัชนีจะ ครอบคลุมคำสั่งค้นหาเมื่อคอลัมน์ทุกคอลัมน์ที่คำสั่งค้นหาต้องใช้ใน SELECT, WHERE, ORDER BY และ GROUP BY มีอยู่ในตัวดัชนีเอง

เมื่อเป็นเช่นนั้น กลไกฐานข้อมูลจะอ่านเฉพาะดัชนีและไม่ต้องไปที่ตารางเลย PostgreSQL เรียกวิธีนี้ว่า การสแกนจากดัชนีเท่านั้น ส่วน SQL Server และระบบอื่น ๆ เรียกว่าดัชนีครอบคลุม ผลที่ได้คืออ่านเพจน้อยลงและทำให้คำสั่งค้นหาเร็วขึ้น

ตัวอย่างแบบลงมือทำ: คำสั่งค้นหาที่ดัชนีครอบคลุม

สมมติว่าคำสั่งค้นหาต้องใช้เพียง customer_id และ order_date ดัชนีผสมที่มีคอลัมน์ทั้งสองนี้พอดีจะมีข้อมูลทุกอย่างที่คำสั่งค้นหาต้องการ จึงสามารถตอบคำสั่งค้นหาได้จากดัชนีเพียงอย่างเดียว

CREATE INDEX idx_orders_cust_date
  ON orders (customer_id, order_date);

-- Covered: both selected columns are in the index
SELECT customer_id, order_date
FROM orders
WHERE customer_id = 42;

คอลัมน์เพิ่มเติมเพียงคอลัมน์เดียวก็ทำให้ไม่ครอบคลุม

เมื่อเพิ่มคอลัมน์ที่ไม่มีอยู่ในดัชนี การครอบคลุมจะหายไป และกลไกฐานข้อมูลต้องดึงข้อมูลจากฮีปเพื่ออ่านคอลัมน์นั้น

ในกรณีนี้ total ไม่ได้อยู่ในดัชนี ดังนั้นแม้ customer_id จะเป็นตัวนำการค้นหาแบบเจาะจง แต่ทุกแถวที่ตรงกันก็ยังต้องดึงข้อมูลจากฮีปเพื่ออ่าน total

-- NOT covered: total is not in the index, forces heap fetches
SELECT customer_id, order_date, total
FROM orders
WHERE customer_id = 42;

คำสั่ง INCLUDE

คุณอาจเพิ่ม total เป็นคอลัมน์คีย์ลำดับที่สี่ได้ แต่หากไม่เคยใช้คอลัมน์นี้กรองหรือเรียงลำดับ ก็จะทำให้สิ้นเปลืองพื้นที่ในลำดับการเรียงของโครงสร้างต้นไม้ เครื่องมือที่เหมาะสมกว่าคือ INCLUDE ซึ่ง PostgreSQL และ SQL Server รองรับ โดยจะเก็บคอลัมน์เพิ่มเติมไว้เฉพาะใน โหนดใบของดัชนีในฐานะข้อมูลประกอบ ไม่ใช่ส่วนหนึ่งของคีย์เรียงลำดับ

ตอนนี้คำสั่งค้นหาจะได้รับการครอบคลุมโดยไม่ทำให้ส่วนที่ใช้ค้นหาของดัชนีมีขนาดใหญ่เกินไป

CREATE INDEX idx_orders_cust_date_inc
  ON orders (customer_id, order_date)
  INCLUDE (total);

-- Now covered: total is carried in the leaf
SELECT customer_id, order_date, total
FROM orders
WHERE customer_id = 42;

คอลัมน์คีย์เทียบกับคอลัมน์ที่รวมไว้

ความแตกต่างที่ชัดเจนและช่วยสร้างความประทับใจให้ผู้สัมภาษณ์:

  • คอลัมน์คีย์กำหนดลำดับการเรียงและใช้สำหรับ ค้นหาแบบเจาะจงและสแกนช่วงได้ โดยต้องปฏิบัติตามกฎคำนำหน้าซ้ายสุด
  • คอลัมน์ที่รวมไว้จะเก็บไว้เฉพาะในโหนดใบในฐานะข้อมูลเพิ่มเติม ไม่สามารถใช้ค้นหาได้ แต่ช่วยให้ดัชนี ครอบคลุมคำสั่งค้นหาได้มากขึ้น

หลักจำง่าย: คอลัมน์ที่คุณใช้ กรองหรือเรียงลำดับให้ใส่ไว้ในคีย์ ส่วนคอลัมน์ที่คุณใช้เพียง ส่งกลับให้ใส่ไว้ใน INCLUDE

MySQL/InnoDB: ความพิเศษของดัชนีแบบจัดกลุ่ม

แสดงให้เห็นว่าคุณเข้าใจความแตกต่างระหว่างระบบฐานข้อมูล InnoDB (MySQL) จะจัดกลุ่มตารางตาม คีย์หลัก ดัชนีรองจึงมีคอลัมน์คีย์หลักติดมาด้วยโดยปริยาย ดังนั้นดัชนีรองจึงครอบคลุมคำสั่งค้นหาทุกคำสั่งที่เลือกเฉพาะคอลัมน์ในดัชนีและคอลัมน์คีย์หลักได้โดยอัตโนมัติ โดยไม่ต้องใช้คำสั่ง INCLUDE (MySQL ไม่มี INCLUDE)

แนวคิดเรื่องการครอบคลุมเป็นสากล แต่ไวยากรณ์และคอลัมน์ที่ได้มาโดยอัตโนมัติจะแตกต่างกันไปตามกลไกฐานข้อมูล

การตรวจสอบการสแกนจากดัชนีเท่านั้น

พิสูจน์การครอบคลุมด้วย EXPLAIN ใน PostgreSQL โหนดของแผนการทำงานจะระบุว่า การสแกนจากดัชนีเท่านั้น แทนที่จะเป็น Index Scan ให้สังเกต Heap Fetches: 0 ใน EXPLAIN (ANALYZE) ซึ่งเป็นสัญญาณยืนยันว่าไม่มีการเข้าถึงตารางเกิดขึ้น

หากคุณคาดว่าจะเห็นการสแกนจากดัชนีเท่านั้น แต่กลับเห็น Index Scan พร้อมการดึงข้อมูลจากฮีป แสดงว่าคอลัมน์ที่เลือกมีคอลัมน์หนึ่งไม่ได้อยู่ในดัชนี

EXPLAIN (ANALYZE)
SELECT customer_id, order_date, total
FROM orders
WHERE customer_id = 42;
-- Look for: Index Only Scan ... Heap Fetches: 0

ข้อควรระวังเรื่องแผนผังการมองเห็นของ PostgreSQL

ประเด็นเล็กน้อยเกี่ยวกับ PostgreSQL ที่ควรตอบเพื่อรับคะแนนพิเศษ: การสแกนจากดัชนีเท่านั้นยังอาจแตะฮีปได้ หากเพจไม่ได้ถูกทำเครื่องหมายว่ามองเห็นทั้งหมดใน แผนผังการมองเห็น หลังจากมีการปรับปรุงข้อมูลจำนวนมาก ให้เรียกใช้ VACUUM เพื่อให้แผนผังการมองเห็นเป็นปัจจุบัน มิฉะนั้นค่า Heap Fetches จะเพิ่มขึ้นและประโยชน์จากการสแกนจากดัชนีเท่านั้นจะลดลง

-- Keeps the visibility map fresh so index-only scans stay heap-free
VACUUM ANALYZE orders;

เมื่อไม่ควรสร้างดัชนีครอบคลุมแบบกว้าง

ดัชนีครอบคลุมไม่ได้ไม่มีต้นทุน การใส่หลายคอลัมน์ไว้ใน INCLUDE ทำให้ดัชนีมีขนาด ใหญ่ ใช้แคชมากขึ้น และทำให้การเขียนช้าลง เพราะการเขียนที่เกี่ยวข้องทุกครั้งต้องปรับปรุงดัชนีด้วย ควรกล่าวถึงข้อแลกเปลี่ยนดังนี้:

  • เหมาะอย่างยิ่งสำหรับคำสั่งค้นหาเพื่ออ่านที่มีขอบเขตแคบและเกิดขึ้นบ่อย
  • ไม่เหมาะสำหรับใช้เป็นที่ทิ้งคอลัมน์ทุกคอลัมน์เผื่อไว้ ‘กรณีจำเป็น’

ทำให้คำสั่งค้นหาที่สำคัญครอบคลุม ไม่ใช่ครอบคลุมทั้งแถว

วิธีอธิบายในการสัมภาษณ์

สรุปได้อย่างชัดเจนดังนี้:

‘ดัชนีครอบคลุมมีคอลัมน์ทุกคอลัมน์ที่คำสั่งค้นหาเข้าถึงอยู่ จึงทำให้กลไกฐานข้อมูลตอบคำสั่งค้นหาได้จากดัชนีเพียงอย่างเดียวด้วยการสแกนจากดัชนีเท่านั้น และไม่ต้องดึงข้อมูลจากฮีป ผมใส่คอลัมน์ที่ใช้ค้นหาไว้ในคีย์ และใส่คอลัมน์ที่ส่งกลับเท่านั้นไว้ใน INCLUDE ตรวจสอบว่าการดึงข้อมูลจากฮีปเป็นศูนย์ด้วย EXPLAIN ANALYZE และทำให้ดัชนีมีขนาดแคบเพื่อรักษาความเร็วในการเขียน’

ตรวจสอบความเข้าใจอย่างรวดเร็ว

วิเคราะห์ว่าดัชนีครอบคลุมหรือไม่ และแต่ละคอลัมน์ควรอยู่ตรงส่วนใด

ทบทวน: ดัชนีครอบคลุม

ประเด็นสำคัญ:

  • ดัชนีจะ ครอบคลุมคำสั่งค้นหาเมื่อมีคอลัมน์ทุกคอลัมน์ที่คำสั่งค้นหาต้องใช้ ทำให้สามารถใช้ การสแกนจากดัชนีเท่านั้นโดยไม่ต้องดึงข้อมูลจากฮีป
  • คอลัมน์คีย์เป็นตัวขับการค้นหาแบบเจาะจงและต้องปฏิบัติตามกฎคำนำหน้าซ้ายสุด ส่วนคอลัมน์ INCLUDEเป็นข้อมูลประกอบที่อยู่เฉพาะในโหนดใบเพื่อให้ครอบคลุมคำสั่งค้นหา
  • ดัชนีรองของ InnoDB จะมีคีย์หลักรวมอยู่ด้วยโดยปริยาย
  • ตรวจสอบด้วย EXPLAIN (ANALYZE) และดูค่า Heap Fetches สำหรับ PostgreSQL ควรเรียกใช้ VACUUM ให้เป็นปัจจุบัน
  • ทำให้ดัชนีครอบคลุมมีขนาด แคบเพื่อรักษาประสิทธิภาพการเขียน

ถัดไป: มุมกลับ เมื่อดัชนีกลับทำให้ประสิทธิภาพแย่ลง

คำถามที่พบบ่อย

บทเรียน “ดัชนีครอบคลุมและการสแกนเฉพาะดัชนี” ฟรีหรือไม่

ใช่ — ข้อความเต็มของ “ดัชนีครอบคลุมและการสแกนเฉพาะดัชนี” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส SQL Interview Prep ให้อัปเกรดเป็น CoddyKit PRO คอร์ส SQL Interview Prep มีบทเรียนทั้งหมด 4 บทเรียน

คุณจะเรียนรู้อะไรในบทเรียน “ดัชนีครอบคลุมและการสแกนเฉพาะดัชนี”

เพิ่มคอลัมน์ที่จำเป็นเพื่อให้คำสั่งค้นหาไม่ต้องเข้าถึงตารางหลัก คุณปฏิบัติ SQL Interview Prep ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน

คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน SQL Interview Prep หรือไม่

ไม่จำเป็นต้องมีประสบการณ์มาก่อน SQL Interview Prep บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 3 จากทั้งหมด 4 บทเรียน

บทเรียน “ดัชนีครอบคลุมและการสแกนเฉพาะดัชนี” ใช้เวลานานแค่ไหน

บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย

ฉันเขียนและรันโค้ดในบทเรียน SQL Interview Prep นี้ได้ไหม

ได้ บทเรียน SQL Interview Prep ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ

บทเรียนทั้งหมดในหลักสูตรนี้

  1. ดัชนี B-Tree และประโยชน์ของดัชนี
  2. ลำดับคอลัมน์ในดัชนีผสม
  3. ดัชนีครอบคลุมและการสแกนเฉพาะดัชนี
  4. เมื่อดัชนีส่งผลเสีย: การเขียนและความสามารถในการเลือกข้อมูล
← กลับไปที่ SQL Interview Prep