Senior #pagination#keyset#offset#performance
Phân trang OFFSET và keyset (seek) khác nhau thế nào?
⚡ Trả lời nhanh
OFFSET n phải quét rồi bỏ n dòng nên càng sang trang sâu càng chậm và dễ lệch dữ liệu khi có insert/delete. Keyset dùng điều kiện trên khoá đã sắp xếp (WHERE id < last_id) nên dùng index, thời gian ổn định, nhưng không nhảy được tới trang bất kỳ.
-- OFFSET: trang 5000 vẫn đọc 100000 dòng rồi bỏ
SELECT * FROM posts ORDER BY id DESC LIMIT 20 OFFSET 100000;
-- Keyset: client gửi id cuối trang trước
SELECT * FROM posts
WHERE id < :last_id
ORDER BY id DESC
LIMIT 20;
-- Sắp xếp theo nhiều cột: row-value comparison + index (created_at, id)
SELECT * FROM posts
WHERE (created_at, id) < (:last_ts, :last_id)
ORDER BY created_at DESC, id DESC LIMIT 20;
- Cột sắp xếp phải duy nhất (thêm
idlàm tie-breaker) để không bỏ sót/trùng dòng. - API thường trả
next_cursor(mã hoá giá trị cuối).