ในโลกของการพัฒนา Web และ Mobile Application การแสดงผลข้อมูลจำนวนมากอย่างเป็นหน้า ๆ หรือที่เรียกว่า “Pagination” เป็นสิ่งที่หลีกเลี่ยงไม่ได้ แต่เมื่อระบบของเราเริ่มเติบโตและต้องจัดการกับชุดข้อมูลขนาดใหญ่หลายล้านรายการ วิธีการ Paginate แบบดั้งเดิมโดยใช้ Offset เช่น LIMIT X OFFSET Y มักจะกลายเป็นคอขวดด้านประสิทธิภาพ (Performance Bottleneck) โดยเฉพาะอย่างยิ่งเมื่อผู้ใช้งานต้องการเข้าถึงหน้าที่ไกลออกไปเรื่อย ๆ
ปัญหาของ Traditional Offset Paging (LIMIT/OFFSET)
Offset Paging ทำงานบนหลักการนับแถวจากจุดเริ่มต้น (Row Count) หากเราขอข้อมูลหน้า 1,000 รายการ ระบบฐานข้อมูลจะต้องทำการประมวลผลเพื่อ “กระโดด” ข้ามบันทึกทั้งก่อนหน้า เพื่อหาว่า Record ที่ 10,001 อยู่ตรงไหน กระบวนการนี้ทำให้เกิดภาระหนัก (Heavy Load) ต่อ Database Engine เพราะมันจำเป็นต้องมีการ Scans พื้นที่ไม่เกี่ยวข้อง (Unnecessary Scans) ทำให้ความเร็วในการโหลดลดลงอย่างเห็นได้ชัด เมื่อค่า OFFSET มีตัวเลขกำกับมากขึ้นเท่าไร ปัญหาก็จะรุนแรงขึ้นเท่านั้น นี่คือเหตุผลสำคัญที่นักพัฒนามืออาชีพจึงต้องหันมาให้ความสนใจกับ Keyset Pagination แทน.
Keyset/Cursor-based Pagination คืออะไร?
Keyset หรือ Cursor-based Pagination ไม่ใช่แค่การบอกจำนวนรายการที่จะแสดง แต่เป็นการระบุ *สถานะ* (State) หรือ *จุดอ้างอิง* ของรายการสุดท้ายที่คุณได้รับมาก่อนหน้านี้ (Cursor) แทนที่จะใช้การนับจำนวนแถว ระบบจะใช้ค่าของคอลัมน์ที่ถูกจัดเรียง (เช่น Primary Key หรือ Timestamp) เป็นตัวกำหนดขอบเขตในการค้นหาข้อมูลถัดไป
หลักการทำงานใน PostgreSQL (The Architecture)
ใน PostgreSQL เราสามารถใช้การเปรียบเทียบค่า (Comparison Operators) บนคอลัมน์ที่จัดเรียง (Sorted Columns) เพื่อให้ฐานข้อมูลสามารถใช้ Index ได้อย่างมีประสิทธิภาพสูงสุด แทนที่จะต้องนับทีละแถว
สมมติว่าเรามีตาราง products ที่มีคอลัมน์ id และ created_at และเราต้องการดึงข้อมูลชุดถัดไปหลังจากที่เราได้รับรายการล่าสุดที่มี id คือ 100 และ created_at คือ ‘2023-10-25 10:00:00’
SQL
SELECT * FROM products WHERE (id, created_at) > (100, '2023-10-25 10:00:00') ORDER BY id, created_at LIMIT 25;
คำอธิบายโค้ด:
WHERE (id, created_at) > (100, '2023-10-25 10:00:00'): นี่คือหัวใจสำคัญ การเปรียบเทียบแบบ Tuple (Compound Key) จะทำให้ PostgreSQL รู้ว่าต้องเริ่มค้นหาจากจุดไหนอย่างแม่นยำORDER BY id, created_at: ต้องมีการจัดเรียงข้อมูลตามคอลัมน์ที่ใช้ในการเปรียบเทียบLIMIT 25: กำหนดจำนวนรายการที่ต้องการในหน้าปัจจุบัน
ข้อดีของการใช้ Keyset Pagination
- ประสิทธิภาพสูง (High Performance): เนื่องจากฐานข้อมูลสามารถใช้ Index ได้อย่างเต็มที่ ทำให้การค้นหาข้อมูลทำได้รวดเร็วมาก ไม่ว่าผู้ใช้จะเข้าถึงหน้าไหนก็ตาม
- ความสามารถในการขยายตัว (Scalability): เหมาะสำหรับแอปพลิเคชันที่ต้องจัดการกับข้อมูลขนาดใหญ่ระดับล้านรายการ
- ความแม่นยำ (Consistency): ลดโอกาสเกิดปัญหาข้อมูลซ้ำหรือข้อมูลหายไปเมื่อมีการแก้ไขข้อมูลในระหว่างการทำ Pagination
บทสรุป
สำหรับนักพัฒนาที่สร้าง API ประสิทธิภาพสูง โดยเฉพาะอย่างยิ่งเมื่อใช้ PostgreSQL การเปลี่ยนจากการใช้ LIMIT/OFFSET ไปสู่ Keyset/Cursor-based Pagination เป็นการยกระดับสถาปัตยกรรมที่สำคัญอย่างยิ่ง การใช้ Tuple Comparison ในเงื่อนไข WHERE ไม่เพียงแต่ช่วยให้โค้ดสะอาดขึ้น แต่ยังช่วยให้ระบบของคุณสามารถรองรับการเติบโตของข้อมูลได้อย่างไร้ขีดจำกัด ทำให้ API ของคุณมีประสิทธิภาพและเชื่อถือได้ในระดับ Senior Architect.