PlusMagi's Blog By Pitt Phunsanit Database Query Refactoring Checklist: เทคนิคปรับแก้คำสั่ง SQL เพื่อหลีกเลี่ยง Full Table Scan บน Production

Query Refactoring Checklist: เทคนิคปรับแก้คำสั่ง SQL เพื่อหลีกเลี่ยง Full Table Scan บน Production

ในฐานะ Senior Architect ที่ต้องรับผิดชอบระบบ Production ที่มีปริมาณข้อมูลมหาศาล ประสิทธิภาพของฐานข้อมูล (Database Performance) คือหัวใจสำคัญของการดำเนินงาน การที่ระบบเกิดอาการหน่วงหรือ Time Out มักมีสาเหตุหลักมาจากคำสั่ง SQL ที่ทำงานได้ไม่เหมาะสม โดยเฉพาะอย่างยิ่งการเกิดภาวะ Full Table Scan ซึ่งเป็นสัญญาณอันตรายที่บ่งชี้ว่าฐานข้อมูลต้องอ่านข้อมูลทุกแถวในตารางแทนการใช้ดัชนี (Index) ที่ควรจะทำได้

ทำความเข้าใจ Full Table Scan ใน PostgreSQL

Full Table Scan คือการที่ Query Optimizer ถูกบังคับให้สแกนข้อมูลทั้งหมดในตารางตั้งแต่ต้นจนจบเพื่อหาข้อมูลที่ตรงตามเงื่อนไข (WHERE clause) ซึ่งกระบวนการนี้ใช้ทรัพยากร I/O และ CPU สูงมาก ทำให้เกิดคอขวด (Bottleneck) อย่างรุนแรงเมื่อตารางมีขนาดใหญ่ขึ้นเรื่อยๆ การแก้ไขปัญหานี้จึงไม่ได้อยู่ที่การเพิ่มฮาร์ดแวร์เพียงอย่างเดียว แต่ต้องอยู่ที่การปรับปรุงคำสั่ง SQL และโครงสร้าง Index อย่างชาญฉลาด

Query Refactoring Checklist: แนวทางป้องกัน Full Table Scan

การทำ Query Refactoring คือการปรับโครงสร้างคำสั่ง SQL ให้มีประสิทธิภาพสูงสุด โดยเฉพาะอย่างยิ่งเมื่อใช้ PostgreSQL นี่คือ 7 เทคนิคสำคัญที่ต้องตรวจสอบ:

  1. การสร้าง Composite Indexes: แทนที่จะสร้าง Index แยกกันหลายตัว ควรพิจารณาสร้าง Composite Index ในคอลัมน์ที่ถูกใช้ร่วมกันในเงื่อนไข WHERE หรือ JOIN เช่น สถานะ (status) และวันที่สร้าง (created_at)
  2. หลีกเลี่ยงการใช้ฟังก์ชันบนคอลัมน์ Indexed: การใช้ฟังก์ชันทางคณิตศาสตร์หรือสตริงกับคอลัมน์ใน WHERE clause เช่น WHERE LOWER(email) = 'test' จะทำให้ PostgreSQL ไม่สามารถใช้ Index ได้ ต้องสแกนทั้งหมด
  3. ใช้ Explicit Join: ระบุประเภทของ JOIN (INNER, LEFT, RIGHT) อย่างชัดเจน แทนการใช้ Comma ใน SELECT list เพื่อเชื่อมตาราง
  4. ระบุคอลัมน์ที่ต้องการ (SELECT * คือศัตรู): ไม่ควรใช้ SELECT * ใน Production ควรระบุเฉพาะคอลัมน์ที่จำเป็นเท่านั้น เพื่อลดปริมาณข้อมูลที่ต้องอ่านและส่งผ่านเครือข่าย
  5. ใช้ CTEs (Common Table Expressions): สำหรับ Query ที่ซับซ้อนมาก การใช้ CTEs (WITH ... AS) ช่วยให้โค้ดอ่านง่ายขึ้นและช่วยให้ Optimizer จัดการกับชุดข้อมูลย่อยๆ ได้อย่างเป็นระบบ
  6. การจัดการ Data Type: ตรวจสอบให้แน่ใจว่าคอลัมน์ที่ใช้ในการเปรียบเทียบมี Data Type ที่ถูกต้องและสอดคล้องกัน
  7. การใช้ `EXPLAIN ANALYZE`: นี่คือเครื่องมือที่สำคัญที่สุด! ต้องใช้คำสั่งนี้เสมอเพื่อตรวจสอบว่า PostgreSQL วางแผนการทำงานอย่างไร และยืนยันว่า Index ถูกใช้งานจริง

ตัวอย่างการปรับแก้ Query (PostgreSQL)

สมมติว่าเรามีตาราง user_data ที่มีคอลัมน์ email และ status

SQL

-- ❌ Bad Practice: Full Table Scan อาจเกิดขึ้นหากไม่มี Index หรือใช้ฟังก์ชัน */
SELECT * FROM user_data WHERE LOWER(email) = '[email protected]';

✅ Good Practice: ปรับแก้โดยการใช้ Index และแก้ไข Query

SQL

-- 1. สร้าง Composite Index ที่เหมาะสม */
CREATE INDEX idx_user_email_status ON user_data (email, status); 

-- 2. ปรับ Query ให้ใช้ Index ได้โดยตรง */
SELECT user_id, username FROM user_data WHERE email = '[email protected]' AND status = 'active';

บทสรุปสำหรับสถาปนิกระบบ

การป้องกัน Full Table Scan ไม่ใช่แค่การเพิ่ม Index แต่คือการเข้าใจถึงกลไกการทำงานของ Query Optimizer ของ PostgreSQL อย่างลึกซึ้ง ก่อน Deploy โค้ดใหม่ที่มีการเปลี่ยนแปลง Query ใดๆ ควรทำการทดสอบประสิทธิภาพด้วย EXPLAIN ANALYZE เสมอ และควรจัดทำ Query Refactoring Checklist นี้ให้เป็นส่วนหนึ่งของกระบวนการ Code Review เพื่อให้มั่นใจว่าระบบ Production ของเราจะมีความเสถียรและสามารถรองรับการเติบโตของข้อมูลได้อย่างยั่งยืน