Thông thường, khi nghĩ đến phân trang người ta sẽ nghĩ ngay đến việc dùng offset:

SELECT u.id, u.date, u.note, u.user_id
FROM user_notes AS u
ORDER BY u.date DESC, u.id DESC
LIMIT 1000 OFFSET 900000;

Tuy nhiên, cách làm này có một nhược điểm là DBMS phải duyệt qua n record để đến được offset.

Thay vào đó, ta có thể sử dụng cursor pagination - tận dụng con trỏ để nhảy đến vị trí cần truy xuất data nhanh hơn. Về bản chất, thay vì dùng offset, ta sử dụng điều kiện WHERE ở trên một (hoặc nhiều) cột có giá trị duy nhất mà được đánh index.

CREATE INDEX idx_user_notes_date_id ON user_notes (date DESC, id DESC); -- composite index on date and id
 
SELECT u.id, u.date, u.note, u.user_id
FROM user_notes AS u
WHERE (u.date, u.id) <= (@date, @lastId)
ORDER BY u.date DESC, u.id DESC
LIMIT 1000;

Trong câu truy vấn trên, @date@lastId là giá trị của record cuối cùng trên trang trước đó.

Resources