Keyset Pagination (Phân trang theo khóa)

Phân trang đúng cách - thay thế LIMIT OFFSET cho page lớn.

Vấn đề #1: Thứ tự sắp xếp không ổn định

-- ❌ Sai: nhiều user cùng firstname có thể xuất hiện ở 2 page
SELECT * FROM users ORDER BY firstname LIMIT 20 OFFSET 40;
 
-- ✅ Đúng: thêm primary key để đảm bảo unique ordering
SELECT * FROM users ORDER BY firstname, lastname, user_id LIMIT 20 OFFSET 60;

Vấn đề #2: OFFSET chậm với page lớn + data thay đổi

-- ❌ LIMIT OFFSET: page 1000 phải ĐỌC VÀ BỎ 999 × 30 = 29,970 rows
SELECT * FROM users ORDER BY firstname, lastname, id LIMIT 30 OFFSET 29970;
 
-- ✅ Keyset Pagination: dùng giá trị row cuối của trang trước làm điểm bắt đầu
SELECT * FROM users
WHERE (firstname, lastname, id) > ('Huy', 'Nguyen', 3150)
ORDER BY firstname, lastname, id
LIMIT 30;
-- Nhanh hơn RẤT nhiều cho page lớn (fast lookup + đọc 30 entries)
-- Nhược: không hỗ trợ nhảy thẳng đến page bất kỳ

Với index trên (firstname, lastname, id): database Fast Lookup đến vị trí row cuối trang trước rồi scan 30 entries - chi phí không đổi dù ở page 1 hay page 10,000. Data thêm/xóa giữa chừng cũng không làm lệch trang (không bị skip/duplicate như OFFSET).

Liên quan