Indexing Safe Lives and Of course Sleepless Nights
1.Index คืออะไร
index แปลตรงตัวเป็นภาษาไทยว่า “ดัชนี” ให้นึกถึงเวลาเราซื้อหนังสือบางเล่มจะมีดัชนีอยู่ท้ายเล่ม โดยเรียงคำที่น่าสนใจในหนังสือตามตัวอักษร ก-ฮ และ A-Z และระบุหน้าในหนังสือไว้เพื่อให้เราสามารถเปิดไปอ่านสิ่งที่เราสนใจในหน้านั้นๆ ได้เลยไม่ต้องเริ่มไล่หาตั้งแต่หนังสือหน้าที่ 1 ถึงหน้าสุดท้าย ในทาง Database index ก็ทำหน้าที่คล้ายกันคือจะเรียกข้อมูลตามตัวอักษร และเก็บที่อยู่ของข้อมูลชุดนั้นๆ ว่าอยู่ตำแหน่งไหนใน Database แล้วถ้าถามว่า Database อะไรต้องทำ index บ้าง คำตอบคือทุก Database ไม่ว่าจะเป็น SQL, NOSQL, etc.
2.ความสำคัญของ Index
index ช่วยเพิ่มประสิทธภาพในการ query data อย่างมาก ถึงขนาดว่าระบบและDB จะล่มไม่ล่มขึ้นอยู่กับ index เลยทีเดียว โดยเฉพาะอย่างยิ่ง trasaction table หรือ trasaction collection ที่มีการอ่านเขียนตลอดเวลามีข้อมูลจำนวนมหาศาล ถ้าไม่มี index ก็ต้อง scan หาข้อมูลจาก record ที่ 1 ถึงสุดท้าย เหมือนเราอ่านหนังสือที่ไม่มีสารบัญและดัชนีคงเหนื่อยเปลืองเวลาและทรัพยากรน่าดู เพราฉะนั้นการออกแบบ Database ในการทำระบบใหม่ หรือการเพิ่มฟีเจอร์ใหม่ๆที่ทีการเพิ่ม query ใหม่ๆ หรือมีการเพิ่ม table ใหม่ต้องมีการวางแผนการสร้าง index ใน การออกแบบควบคู่ไปตั้งแต่ต้น เนื่องจากถ้าเรารอให้ข้อมูลในระบบมีจำนวนมากแล้วค่อยทำ index อาจจะรู้ตัวเมื่อระบบล่มไปแล้ว และการทำ index ในขณะที่ระบ live อยู่ อาจจะกระทบ perfomance ของระบบ อาจถึงขั้นต้องปิดระบบทำแล้วแต่ความสามารคขอ Database ที่เราเลือกใช้
3.ตัวอย่างการทำ Index
ผมขอยกตัวอย่างในการทำ index ของ MongoDB ซึ่ง Database ตัวอื่นๆ SQL , NOSQL ก็มีหลักการทำคล้ายๆ กัน
ตัวอย่างเรามี collection Employee มี record ดังนี้
{"_id": ObjectId(“570c04a4ad233577f97dc459”),"employNo": 88,"name": "Alan","age": 30"employmentDate": "2020–01–01""department": "product development"}
3.1Single Field Index
เป็นการ index field เดียว สมมติต้องการหาพนักงานโดยใช้ employNo
db.employees.find({ employNo: 88})
create index :
db.employees.createIndex({ "employNo": 1 })
ตัวอย่างการทำ index field employNo และ ตัวเลข 1ที่ะบุ คือ เราจะเรียง index ตามตัวอักษรจากน้อยไปมาก (ascending ) ให้ใส่เลข 1 หรือจากมากไปน้อย (descending ) ให้ใส่ -1 ประโยชน์ของการเรียงจะช่วยในการ sort data ซึ่งจะกล่าวต่อไป
3.2 Compound Indexes
เป็นการ index มากกว่า 1 field สมมติต้องการหาพนักงานที่อยู่แผนก human resource และ เริ่มงานในปี 2002
db.employees.find({ department: “human resource” , employmentDate: { $gte : “2022–01–01” }})
create index :
db.employees.createIndex({ "department": 1, "employmentDate": 1 })
ลำดับในการสร้าง compound index มีความสำคัญตัว index นี้สามารถใช้กับการ query หาพนักงานทั้งหมดที่อยู่ในแผนกได้ด้วยเพราะเรา index department เป็นลำดับแรกดังนี้
db.employees.find({ department: "human resource" })
แต่ไม่สามารถ query โดยใช้ employmentDate ดังนี้
db.employees.find({ employmentDate: { $gte : "2022-01-01" }})
3.3 ลำดับการเรียง ascending หรือ descending
ลำดับการเรียง index มีประโยชน์ในการช่วย sort ได้
Ex.1 compound index sort ไปในทิศทางเดียวกัน
db.employees.createIndex({ "department": 1, "employmentDate": 1 })db.employees.createIndex({ "department": -1, "employmentDate": -1})
index ทั้ง 2 แบบด้านบน สามารถช่วยในการ sort query ได้ทั้ง 2 แบบนี้ดังนี้
db.employees.find().sort({ department: 1, employmentDate1 })db.employees.find().sort({ department: -1, employmentDate-1 })
แต่ไม่สามารถ query sort คนละทาง ดังต่อไปนี้ได้
db.employees.find().sort({ department: -1, employmentDate : 1 })db.employees.find().sort({ department: 1, employmentDate : -1 })
Ex.2 compound index sort สลับทิศทาง
db.employees.createIndex({ “department”: 1, “employmentDate”: -1 })db.employees.createIndex({ “department”: -1, “employmentDate”: 1 })
index ทั้ง 2 แบบ ด้านบน สามารถช่วยในการ sort query ได้ทั้ง 2 แบบนี้
db.employees.find().sort({ department: 1, employmentDate:-1 })db.employees.find().sort({ department: -1, employmentDate:1 })
แต่ไม่สามารถ query sort ไปทางเดียว ดังต่อไปนี้ได้
db.employees.find().sort({ department: 1, employmentDate : 1 })db.employees.find().sort({ department: -1, employmentDate : -1 })
Ex.3 การที่จะให้ index sort โดยมีเงื่อนไน query ด้วย มีข้อแม้ว่าเงื่อนไขต้องเป็น เท่ากับเท่านั้น
db.employees.createIndex({ “department”: 1, “employmentDate”: -1 })
สามารถใช้ query โดย department ต้องเป็น operater “เท่ากับ” เท่านั้น index จะช่วยทั้งเงื่อนไขการค้นหา และ การเรียงลำดับข้อมูล
db.employees.find({ department: “human resource” }).sort({ employmentDate: 1 })
references:
หากชอบบทความของ FlowAccount Tech Blog อย่าลืมกด Follow นะครับ ติดตามบทความอื่นจาก FlowAccount Tech Blog ได้ที่ https://medium.com/flowaccount-tech
Open Positions jobs available on FlowAccount > https://flowaccount.com/en/jobs