ปัญหาอย่างหนึ่งของ developer ที่มักจะเจอก็คือ ไม่เข้าใจว่า index นั้นทำงานอย่างไร, ทำอะไรได้บ้าง, แต่ละแบบแตกต่างกันอย่างไร ในบทความนี้จะเป็นการเปรียบเทียบการทำงานของ index โดยอาศัยภาพประกอบเพื่อให้เข้าใจมากยิ่งขึ้นนั่นเอง
Cautions
MongoDB นั้นไม่ได้ทำงานเหมือนเรื่องที่จะเล่า แต่เพื่อให้เข้าใจง่ายที่สุด เลยต้องตัดความซับซ้อนออกไป ผู้อ่านควรศึกษาและทำความเข้าใจเรื่องของ index ต่อหลังจากอ่านจบแล้วด้วยครับ
เราจะจำลองสถานการณ์ของ Adam กับ Eve เล่นเกมตอบคำถามกัน โดย Adam จะถามว่า X อยู่ในกล่องตำแหน่งที่เท่าไหร่ (1, 2, 3, ..., n)
โดยกฏของเกมนี้คือ
Adam จะถามคำถาม 2 รอบ
Eve จะต้องตอบคำถามครั้งที่ 2 ให้ได้ โดยที่ใช้เวลาไม่เกิน 1 วินาที
ในการมองแต่ละครั้ง Eve จะใช้เวลามากกว่า 1 วินาทีเสมอ
Eve ต้องเริ่มมองจากซ้ายสุดก่อนเสมอ
ถ้า Eve ใช้เวลาในการตอบคำถามที่ 2 เกิน 1 วินาที Eve จะเป็นฝ่ายแพ้
note: ถ้าสมมติว่า adam ถามเป็น query การที่ eve มองก็เท่ากับ scanning โดยที่แต่ละวัตถุคือ document และตำแหน่งของวัตถุก็คือตำแหน่งของ document และวัตถุ X ที่เป็นคำตอบคือ item ที่อยู่ในกล่อง (document)
1. Without Indexes
Adam ถามครั้งแรกว่า "วงกลมอยู่ลำดับที่เท่าไหร่?" Eve จึงเริ่มมองหาจากซ้ายไปขวา ซึ่งก็คือสี่เหลี่ยม, สามเหลี่ยม, หัวใจ, ดาว, วงกลม Eve จึงตอบออกไปว่า วงกลมอยู่อันดับที่ 5
db.collection.find( { "shape": "circle" } )
Adam จึงถามอีกครั้งว่า "วงกลมอยู่ลำดับที่เท่าไหร่?" ซึ่งในรอบนี้ Eve ต้องตอบคำถามโดยที่ใช้เวลาไม่เกิน 1 วินาที Eve ก็เริ่มมองจากซ้ายไปขวาใหม่ ซึ่งก็คือสี่เหลี่ยม, สามเหลี่ยม, หัวใจ, ดาว, วงกลม หลังจากใช้เวลาอยู่พอสมควร Eve ถึงจะตอบได้ว่าอยู่อันดับที่ 5
รอบนี้ Eve จึงได้แพ้ไป เพราะไม่สามารถที่จะตอบได้เร็วกว่า 1 วินาทีนั่นเอง
reminder: การมองแต่ละครั้งใช้เวลามากกว่า 1 วินาที
2. With Indexes
Adam ถามคำถามแรก ซึ่งเป็นคำถามเดิมว่า "วงกลมอยู่ลำดับที่เท่าไหร่?" Eve จึงเริ่มมองหาจากซ้ายไปขวา ซึ่งก็คือสี่เหลี่ยม, สามเหลี่ยม, หัวใจ, ดาว, วงกลม Eve จึงตอบออกไปว่า วงกลมอยู่อันดับที่ 5...
แต่รอบนี้ Eve ซึ่งแพ้มาจากรอบที่แล้วเริ่มรู้ตัวว่า ถ้า Adam ถามคำถามเดิม เธอจะใช้เวลานานแน่ๆ Eve เป็นคนที่มีความจำดีมากๆ หาก Eve จำอะไรได้จะนึกออกได้ในเสี้ยววินาที!
db.collection.createIndex( { shape: 1 } )
Eve จึงเริ่มคิดเริ่มคิดที่จะเอาชนะด้วยการจำซะเลยว่าอะไร อยู่ตำแหน่งไหน
Adam ถามด้วยคำถามที่สองว่า "วงกลม อยู่ในกล่องที่เท่าไหร่?" ซึ่งก็เป็นไปตามคาด! Eve ซึ่งมีคำตอบอยู่ในใจที่ท่องจำไว้แล้ว จึงสามารถตอบออกไปได้ทันทีว่า 5!
รอบนี้ชัยชนะตกเป็นของ Eve เพราะว่าสามารถตอบได้ด้วยเวลาน้อยอันน้อยนิด ซึ่งการที่ Eve จำเอาไว้ในใจก็คือการทำ Index นั่นเอง
Adam ชักไม่แน่ใจ ที่อีฟตอบมานั่นมั่วหรือปล่าว ทำไมเร็วจัง? Adam จึงลองถามใหม่แบบไม่สนแพ้ชนะว่า "หัวใจ อยู่ในกล่องอันดับที่เท่าไหร่?
Eve นึกดูแล้วจำไม่ได้ว่าหัวใจอยู่ในกล่องลำดับที่เท่าไหร่ จึงต้องเริ่มมองหาใหม่อีกครั้งถึงจะตอบได้
ในความเป็นจริงแล้ว Eve ต้องมองหาต่อจนถึงอันสุดท้าย (ขวาดสุด) เพราะ Eve ไม่มีทางรู้เลยว่าอันที่เหลือจะมีหัวใจอีกไหม (นอกจากจะจำได้หมด)
Adam สังเกตุเห็นว่ารอบนี้ Eve ใช้เวลานานกว่า 1 วินาที Adam จึงจับทางได้แล้วว่า Eve ใช้วิธีจำเอาเลยตอบได้ไว จึงได้คิดจะหาทางเอาชนะ Eve
ถ้ารอบหน้าเขาถามหาหัวใจหรือวงกลมอีก Eve ก็จะสามารถตอบได้ไวแน่นอนเพราะ Eve จำได้แล้ว! เขาต้องเลี่ยงที่จะถามหาวงกลมหรือหัวใจ...
3. Covered query
Adam จึงเริ่มถามคำถามที่สองทันทีว่า "สี่เหลี่ยม อยู่ในกล่องลำดับที่เท่าไหร่?" ซึ่งรอบนี้ Eve ต้องตอบให้ได้ภายในเวลาน้อยกว่า 1 วินาทีเพื่อที่จะชนะ Eve ที่จำได้แค่วงกลมกับหัวใจ จึงตอบออกไปทันทีว่า ไม่รู้!
เทคนิคที่ Eve ใช้ในการตอบให้เร็วขึ้นคือ Covered query นั่นเอง เป็นการโฟกัสเฉพาะสิ่งที่อยู่ในความจำเท่านั้น ไม่สนใจอย่างอื่นนอกจากนี้
Eve บอกว่ากติกาคือตอบเร็ว ไม่ได้ห้ามตอบว่าไม่รู้สักหน่อย Adam จึงยอมรับความพ่ายแพ้ในรอบนี้ไปแบบไม่เต็มใจนัก
note: ในทางปฎิบัติคนที่จะใช้งาน covered query คือคนสั่ง query (Adam) ไม่ใช่ทางคนรับ (Eve) ตัวอย่างนี้ทำขึ้นเพื่อให้เข้าใจ concept ของ covered query ที่ search space จะเป็นสิ่งที่ทำ index ไว้เท่านั้น