ทำความเข้าใจ Indexing หัวใจสำคัญของการค้นหาข้อมูล
เวลาเราพูดถึงฐานข้อมูล Indexing (การทำดัชนีหรือสารบัญข้อมูล) มันก็เหมือนกับการเปิดดูหนังสือเล่มหนา ถ้าไม่มีสารบัญ เราก็ต้องไล่อ่านตั้งแต่หน้าแรกจนจบเพื่อหาหัวข้อที่ต้องการ ซึ่งมันเสียเวลามาก การทำ Index ในฐานข้อมูลจึงเป็นการสร้างตารางสรุปไว้ท้ายเล่ม เพื่อบอกว่าข้อมูลที่เราต้องการนั้นถูกจัดเก็บไว้ที่ตำแหน่งไหนของตารางหลัก
สำหรับโปรแกรมเมอร์มือใหม่ การเข้าใจเรื่องนี้สำคัญมาก เพราะตอนที่คุณฝึกเขียนโปรแกรมช่วงแรก ข้อมูลอาจจะมีแค่ไม่กี่บรรทัดจนไม่รู้สึกถึงความต่าง แต่พอทำโปรเจกต์จริงที่มีข้อมูลเป็นแสนเป็นล้านแถว Query (คำสั่งถามข้อมูลจากฐานข้อมูล) ของคุณจะทำงานช้าลงจนแอปฯ ค้างทันทีถ้าไม่มีการทำดัชนีที่ดี
เรามาเริ่มเปรียบเทียบให้เห็นภาพชัดๆ กันก่อน ถ้าคุณมีรายชื่อพนักงาน 1 ล้านคนในตาราง การหาชื่อ "สมชาย" โดยไม่มีดัชนี คอมพิวเตอร์ต้องไล่เช็กทีละแถวตั้งแต่คนแรกจนถึงคนสุดท้าย นี่คือสิ่งที่เรียกว่า Table Scan (การกวาดอ่านข้อมูลทั้งตาราง) ซึ่งเป็นฝันร้ายของประสิทธิภาพการทำงานในฐานข้อมูล
Clustered Index คือการจัดเรียงข้อมูลตัวจริง
Clustered Index (การจัดเรียงข้อมูลแบบกลุ่ม) คือการเอาข้อมูลในตารางมาเรียงลำดับใหม่จริงๆ บนฮาร์ดดิสก์ ตามคอลัมน์ที่เราเลือกไว้ เปรียบเหมือนพจนานุกรมที่เรียงคำศัพท์จาก ก ถึง ฮ ตามตัวอักษรอยู่แล้ว เมื่อมันเรียงกันแบบนี้ การหาข้อมูลจึงทำได้รวดเร็วและแม่นยำมาก
ในหนึ่งตาราง คุณสามารถมี Clustered Index ได้เพียงหนึ่งอันเท่านั้น เพราะข้อมูลหนึ่งชุดจะถูกเรียงลำดับในหน้ากระดาษได้เพียงรูปแบบเดียว ปกติแล้วโปรแกรมเมอร์มักจะเลือกใช้ Primary Key (คีย์หลักที่ระบุตัวตนของข้อมูลไม่ให้ซ้ำกัน) เป็นตัวกำหนดดัชนีประเภทนี้
ข้อควรระวังคือ ถ้าคุณเลือกคอลัมน์ที่มีการแก้ไขข้อมูลบ่อยๆ มาทำดัชนีประเภทนี้ จะทำให้ระบบทำงานหนัก เพราะทุกครั้งที่มีข้อมูลใหม่แทรกเข้ามา คอมพิวเตอร์ต้องเสียเวลาขยับข้อมูลแถวอื่นเพื่อให้ลำดับยังคงถูกต้องอยู่เสมอ
-- สร้างตารางพร้อมกำหนด Clustered Index ที่คอลัมน์ EmployeeID
CREATE TABLE Employees (
EmployeeID INT PRIMARY KEY, -- Primary Key จะสร้าง Clustered Index ให้โดยอัตโนมัติ
Name NVARCHAR(100),
Department NVARCHAR(50)
);
คำอธิบายโค้ด: บรรทัดที่ 2 คือการกำหนดคอลัมน์ EmployeeID ให้เป็น Primary Key ซึ่ง MS-SQL จะจัดการสร้าง Clustered Index ให้อัตโนมัติในฐานะดัชนีหลักของตารางนี้
ผลลัพธ์ที่ควรเห็น: ตาราง Employees จะถูกสร้างขึ้น และข้อมูลภายในจะถูกเรียงลำดับตาม EmployeeID จากน้อยไปหามากเสมอ ทำให้การเรียกค้นข้อมูลด้วยไอดีทำได้เร็วมาก
Non-Clustered Index ทางลัดที่แยกออกมาต่างหาก
Non-Clustered Index (การทำดัชนีแยกส่วน) เปรียบเหมือนดัชนีคำสำคัญท้ายเล่มหนังสือ มันไม่ได้เปลี่ยนลำดับข้อมูลในตารางหลัก แต่มันสร้างตารางแยกต่างหากที่มีแค่ "คำค้น" กับ "เลขหน้า" ไว้ให้เราวิ่งไปหาข้อมูลได้เร็วขึ้น
เราสามารถสร้าง Non-Clustered Index ได้หลายอันในหนึ่งตาราง เหมือนกับหนังสือที่มีทั้งดัชนีคำศัพท์ ดัชนีชื่อคน หรือดัชนีสถานที่ แยกออกจากกัน คุณสามารถสร้างดัชนีนี้ให้กับคอลัมน์ที่ถูกนำไปใช้ในเงื่อนไข WHERE (คำสั่งกรองข้อมูล) บ่อยๆ ได้เลย
แต่ต้องจำไว้ว่าการสร้างดัชนีเยอะเกินไปก็มีผลเสีย เพราะทุกครั้งที่คุณเพิ่มหรือลบข้อมูลในตารางหลัก ฐานข้อมูลต้องเสียเวลาไปอัปเดตตารางดัชนีแยกเหล่านี้ด้วย ทำให้การบันทึกข้อมูลช้าลง อย่าสร้างดัชนีพร่ำเพรื่อ ให้สร้างเฉพาะคอลัมน์ที่ใช้ค้นหาจริงๆ เท่านั้น
-- สร้าง Non-Clustered Index เพื่อเร่งความเร็วในการค้นหาชื่อพนักงาน
CREATE NONCLUSTERED INDEX IX_Employees_Name
ON Employees(Name);
คำอธิบายโค้ด: บรรทัดที่ 1 คือการสั่งสร้างดัชนีชื่อ IX_Employees_Name แยกออกมาต่างหาก บรรทัดที่ 2 ระบุว่าให้ทำดัชนีบนคอลัมน์ Name ในตาราง Employees
ผลลัพธ์ที่ควรเห็น: เมื่อมีการรันคำสั่งค้นหาโดยใช้ชื่อ เช่น SELECT * FROM Employees WHERE Name = 'Somchai' ฐานข้อมูลจะไปเช็กที่ตารางดัชนี IX_Employees_Name ก่อน แล้วค่อยวิ่งไปดึงข้อมูลจริงจากตารางหลัก ทำให้ไวกว่าการไล่หาข้อมูลทีละแถว
วิเคราะห์ Graphical Execution Plan ใน SSMS
Graphical Execution Plan (แผนผังการทำงานแบบรูปภาพ) ใน SSMS (เครื่องมือจัดการฐานข้อมูลของ Microsoft) คือเครื่องมือที่บอกเราว่าฐานข้อมูล "คิด" อย่างไรก่อนจะแสดงผลลัพธ์ออกมา มันจะวาดแผนภาพแสดงขั้นตอนการทำงานให้เราเห็นว่ามันไปหยิบข้อมูลมาจากไหน
วิธีใช้งานคือ ให้คุณเปิด Query Window (หน้าต่างพิมพ์คำสั่ง) แล้วกดปุ่ม Include Actual Execution Plan บนแถบเครื่องมือ หรือกดปุ่ม Ctrl + M ก่อนจะรันคำสั่ง Query ของคุณ เมื่อรันเสร็จแล้ว จะมีแท็บใหม่ชื่อ Execution Plan โผล่ขึ้นมาให้คลิกดู
ในแผนภาพนี้ คุณจะเห็นสัญลักษณ์ต่างๆ เช่น Index Seek (การหาข้อมูลตรงจุดที่ดัชนีบอก) หรือ Table Scan ถ้าคุณเห็นคำว่า Table Scan ในตารางที่มีข้อมูลเยอะๆ นั่นคือสัญญาณเตือนว่า คุณควรสร้างดัชนีในคอลัมน์ที่เกี่ยวข้องได้แล้ว
- เขียนคำสั่ง
SELECTที่ต้องการทดสอบ - กดปุ่ม
Ctrl + Mเพื่อเปิดใช้งานแผนผังการทำงาน - รันคำสั่ง
F5แล้วกดที่แท็บ Execution Plan
ผลลัพธ์ที่ควรเห็น: คุณจะเห็นลูกศรเชื่อมโยงกล่องสี่เหลี่ยมหลายใบ แต่ละใบมีเปอร์เซ็นต์กำกับ ถ้ากล่องไหนมีเปอร์เซ็นต์สูงๆ นั่นคือจุดที่ฐานข้อมูลใช้เวลาทำงานหนักที่สุด
จุดที่มือใหม่มักพลาดและวิธีแก้ไข
ข้อผิดพลาดคลาสสิกของมือใหม่คือการใช้ฟังก์ชันครอบคอลัมน์ที่ทำดัชนีไว้ เช่น WHERE LEFT(Name, 3) = 'Som' การทำแบบนี้จะทำให้ SQL Server ไม่สามารถใช้ดัชนีที่สร้างไว้ได้ และต้องกลับไปใช้วิธี Table Scan เหมือนเดิม เพราะมันไม่รู้ว่าจะเริ่มหาจากตรงไหน
อีกเรื่องคือการทำ Select Star (การดึงข้อมูลทุกคอลัมน์) โดยไม่จำเป็น การดึงข้อมูลมาเกินความจำเป็นจะทำให้ฐานข้อมูลต้องอ่านข้อมูลจากหน้าดิสก์มากกว่าที่ควรจะเป็น ส่งผลให้ความเร็วโดยรวมลดลง ทั้งที่จริงๆ แล้วเราอาจต้องการแค่ 2-3 คอลัมน์เท่านั้น
ทางแก้ที่ดีคือต้องหมั่นตรวจสอบ Execution Plan เสมอเมื่อรู้สึกว่าคำสั่งทำงานช้าลง หากเห็นคำว่า Warning (สัญลักษณ์สามเหลี่ยมสีเหลือง) บนรูปภาพ ให้ลองเอาเมาส์ไปชี้ดู มันมักจะบอกใบ้ว่าควรทำดัชนีเพิ่ม หรือคอลัมน์ไหนที่ขาดหายไป
สรุปการนำไปใช้ในการทำงานจริง
ในการทำงานจริง เมื่อคุณได้รับโปรเจกต์ให้ปรับปรุงความเร็วของระบบ ขั้นตอนแรกคือการดูว่า Query ไหนที่ทำงานช้าที่สุด จากนั้นให้เปิด Execution Plan มาดูว่าฐานข้อมูลกำลังทำ Scan ข้อมูลอยู่หรือไม่ ถ้าใช่ ให้พิจารณาว่าคอลัมน์ไหนในเงื่อนไข WHERE ที่ยังไม่มีดัชนี
สมมติคุณมีระบบค้นหาลูกค้าตามเบอร์โทรศัพท์ แต่ระบบช้ามาก คุณควรสร้าง Non-Clustered Index บนคอลัมน์ Phone ทันที จากนั้นลองรัน Execution Plan อีกครั้ง คุณจะเห็นว่าจากเดิมที่เป็น Table Scan มันจะเปลี่ยนเป็น Index Seek ซึ่งเร็วกว่ามหาศาล
จำไว้ว่าการเป็นโปรแกรมเมอร์ที่เก่งไม่ได้วัดกันแค่เขียนโค้ดได้ แต่คือการเขียนโค้ดที่ "ฉลาด" และใช้ทรัพยากรของระบบอย่างคุ้มค่า การฝึกอ่าน Execution Plan จะช่วยให้คุณเข้าใจการทำงานของฐานข้อมูลลึกซึ้งขึ้น และทำให้แอปพลิเคชันของคุณตอบสนองได้ทันใจผู้ใช้งานเสมอ ความช้าคือศัตรูตัวฉกาจของประสบการณ์ผู้ใช้ จงใช้ดัชนีให้เป็นอาวุธคู่กายครับ