1. 08:55 29/08/2026
Khi một màn hình bắt đầu hiển thị hàng nghìn bản ghi, việc trả toàn bộ dữ liệu trong một lần gọi API sẽ nhanh chóng trở thành vấn đề. Thời gian phản hồi tăng, máy chủ tốn bộ nhớ, còn trình duyệt phải xử lý một lượng dữ liệu không cần thiết. Phân trang và tìm kiếm đúng cách giúp giao diện nhẹ hơn, nhưng nếu thiết kế thiếu nhất quán, người dùng có thể thấy bản ghi trùng lặp, bị bỏ sót hoặc kết quả thay đổi khó hiểu.
1. Chọn kiểu phân trang phù hợp
Phân trang theo số trang, chẳng hạn page=3 và limit=20, dễ triển khai và phù hợp với trang quản trị cần nút chuyển đến trang cụ thể. Tuy nhiên, cách này thường dùng OFFSET trong cơ sở dữ liệu. Khi bảng có nhiều bản ghi, OFFSET lớn có thể khiến hệ quản trị phải đọc và bỏ qua nhiều dòng trước khi trả kết quả.
Phân trang bằng con trỏ, thường truyền cursor hoặc giá trị của bản ghi cuối cùng, phù hợp hơn với danh sách dài như dòng thời gian, thông báo hoặc lịch sử giao dịch. Ví dụ, API có thể nhận limit=20 và cursor chứa id hoặc created_at của phần tử cuối trang trước. Cách này ổn định hơn khi dữ liệu mới liên tục được thêm vào.
2. Luôn xác định thứ tự rõ ràng
Một truy vấn phân trang cần có thứ tự sắp xếp ổn định. Nếu chỉ sắp xếp theo created_at mà nhiều bản ghi có cùng thời điểm, thứ tự giữa chúng có thể thay đổi. Nên dùng thêm một khóa duy nhất làm điều kiện phụ, chẳng hạn ORDER BY created_at DESC, id DESC. Khi dùng cursor, điều kiện truy vấn cũng phải phản ánh đúng thứ tự này để tránh trùng hoặc thiếu bản ghi.
3. Tách tìm kiếm, lọc và sắp xếp
API nên mô tả rõ các tham số được hỗ trợ, ví dụ q cho từ khóa, status cho trạng thái, from và to cho khoảng thời gian, sort cho trường sắp xếp. Không nên cho phép người dùng truyền tùy ý tên cột trực tiếp vào câu lệnh SQL. Hãy ánh xạ một danh sách giá trị được cho phép sang cột tương ứng, vừa dễ kiểm soát vừa giảm rủi ro bảo mật.
Với tìm kiếm theo tiền tố hoặc các bộ lọc đơn giản, chỉ mục phù hợp có thể đem lại hiệu quả đáng kể. Trước khi thêm chỉ mục, hãy xem truy vấn thực tế, tần suất sử dụng và chi phí ghi dữ liệu. Không phải cột nào cũng cần lập chỉ mục.
4. Thiết kế phản hồi dễ dùng
Phản hồi API nên cho biết danh sách hiện tại, kích thước trang và thông tin để lấy trang tiếp theo. Với cursor pagination, có thể trả về next_cursor và has_more. Nếu không còn dữ liệu, next_cursor nên có giá trị rỗng hoặc null thống nhất. Giao diện cũng cần xử lý trạng thái đang tải, không có kết quả, lỗi mạng và bộ lọc không hợp lệ.
5. Kiểm tra bằng dữ liệu thay đổi liên tục
Đừng chỉ thử với một bảng nhỏ. Hãy kiểm tra khi bản ghi mới được thêm trong lúc người dùng đang cuộn, khi một bản ghi bị xóa, khi hai bản ghi có cùng thời gian tạo và khi người dùng bấm tải lại nhiều lần. Các trường hợp này thường bộc lộ lỗi mà việc kiểm thử thông thường bỏ qua.
Một cách triển khai thực tế là bắt đầu bằng giới hạn trang hợp lý, whitelist bộ lọc và sắp xếp, sau đó đo truy vấn bằng dữ liệu gần với môi trường thật. Khi danh sách cần cuộn vô hạn hoặc dữ liệu thay đổi liên tục, cursor pagination thường là lựa chọn đáng cân nhắc hơn OFFSET.