2. 18:15 12/08/2026
Chào bạn Đức Lâm,
OFFSET phù hợp cho danh sách nhỏ hoặc khi người dùng cần nhảy đến số trang cụ thể. Nhưng với offset rất lớn, MySQL thường vẫn phải đi qua/bỏ qua nhiều dòng trước khi trả về phần cần dùng. Với luồng đọc tuần tự như activity feed, keyset pagination thường ổn định và rẻ hơn.
Thiết kế cursor cần:
1. Xác định thứ tự toàn phần, ví dụ created_at DESC, id DESC. Cột phụ id làm tie-breaker khi nhiều record cùng timestamp.
2. Cursor chứa giá trị của phần tử cuối đã thấy, không phải chỉ số trang. Truy vấn tiếp phải dùng predicate phù hợp với thứ tự, sau đó LIMIT page_size + 1 để biết còn trang hay không.
3. Ký hoặc mã hóa cursor ở phía server nếu nó chứa trạng thái không muốn client sửa; luôn validate cấu trúc, tenant scope và page size.
4. Chấp nhận/định nghĩa rõ behavior khi bản ghi mới xuất hiện hay bản ghi cũ bị xóa. Cursor giúp tránh việc item bị trượt do OFFSET, nhưng không tự tạo snapshot toàn cục qua nhiều request.
5. Có index khớp filter/sort và benchmark bằng dữ liệu lớn thật.
Đừng thêm cursor pagination chỉ vì một trang có OFFSET. Hãy nhìn workload: trải nghiệm UX cần nhảy trang, yêu cầu export, thứ tự dữ liệu và chỉ số latency p95/p99 để quyết định.
0