Hai phương pháp triển khai phân trang phổ biến hiện nay, bạn đang dùng cách nào?

Hai phương pháp triển khai phân trang phổ biến hiện nay, bạn đang dùng cách nào?

Những mẩu tin ngắn hàng ngày dành cho bạn
  • Hẳn là nhiều người ở đây đã nghe đến kiểu tấn công bảo mật Clickjacking rồi nhỉ. Kẻ tấn công thường nhúng một website (thường là mục tiêu) vào trong một iframe trên website của chúng, sau đó làm mờ hoặc ẩn nó đi rồi đặt vào vị trí các nút bấm trên web, ví dụ "Bấm vào để nhận quà". Đâu ai ngờ rằng phía trên nút bấm đó là một nút bấm khác trong iframe. Khá nguy hiểm!

    Nhưng trình duyệt đã có cách ngăn chặn kiểu tấn công này bằng các quy tắc như tiêu đề X-Frame-Options, frame-ancestors của CSP và SameSite: Lax/Strict của Cookies...

    Mới đây, đã xuất hiện thêm kiểu tấn công mới - "DoubleClickjacking" 😨. Đại ý là "hắn" lợi dụng hành động double click để lừa người dùng bấm vào một nút mà hắn muốn. Chi tiết hơn trong bài viết này: DoubleClickjacking: A New Era of UI Redressing.

    » Xem thêm
  • Mọi người đã nghe nói đến Jujutsu - jj - một dạng quản lý phiên bản cho mã nguồn (version control system) chưa? Có vẻ như nó đang nhận được nhiều sự quan tâm.

    Chờ xíu! Chẳng phải git đã quá tốt rồi sao? Thế thì chế ra thằng jj để làm gì nữa? Cũng hơi khó trả lời nhỉ? Mỗi công cụ sinh ra chắc chắn phải cải thiện hoặc khắc phục được nhược điểm của cái trước. Cho nên jj ắt hẳn phải làm được điều gì đó mà git chưa làm được nên mới nổi lên như vậy.

    Thật ra mình đã nghe nói đến jj từ vài tháng trước rồi, nhưng vào đọc thì toàn kiến thức cao siêu. Hoặc là đang mang nặng cái lối suy nghĩ của git vào trong đầu rồi nên chưa lĩnh hội ra được điều gì cả.

    Mình hay có kiểu cái gì đọc lần 1 mà không hiểu thì đọc tiếp lần 2, lần 2 không hiểu thì đọc tiếp lần 3... đến lần thứ n mà vẫn không hiểu thì bỏ. Cơ mà không phải là từ bỏ mà một thời gian sau đó quay lại đọc tiếp. Đến một lúc nào đó khả năng mình sẽ hiểu ra một ít vấn đề, thế mới tài 😆.

    Thì cái jj này có vẻ như nó đang mở ra được tính linh hoạt trong việc "cam kết" mã. Tưởng tượng bạn đang làm việc trên một dự án, đang ở nhánh này, muốn sang nhánh khác để sửa, nhưng mà lại đang viết dở ở nhánh này, thế là phải stash, rồi checkout, rồi commit, rồi merge hoặc rebase lại vào nhánh cũ... nhìn chung quá trình làm việc với git nghiêm ngặt đến mức cứng nhắc, cần nhiều thao tác để giải quyết một vấn đề, chưa kể cái cây commit (commit-tree) nữa thì ôi thôi, khỏi xem cho đỡ nhức mắt. Thế nên ông jj này đang làm cách nào đó để bạn khỏi cần phải quan tâm đến các nhánh luôn, sửa trực tiếp vào commit. Nghe ảo nhỉ 😂.

    Đấy mới lĩnh hội được đến đấy, hy vọng sau n lần đọc lại nữa mình sẽ viết được một bài chi tiết hơn về công cụ này.

    » Xem thêm
  • Gòi gòi tới công chiện gòi 🤤🤤🤤

    » Xem thêm

Vấn đề

Phân trang là một trong những yêu cầu cơ bản đối với API lấy dữ liệu là danh sách. Phân trang nhằm giảm tải lượng dữ liệu cần truy vấn cũng như giảm tải lượng dữ liệu truyền về, vì việc lấy hết dữ liệu trong một danh sách rất dài là một điều lãng phí đối với hầu hết tính năng thông thường.

Bài viết ngày hôm nay tôi xin phép trình bày hai kĩ thuật phân trang phổ biến mà dễ dàng triển khai nhất. Mỗi loại có ưu nhược điểm thế nào và nên áp dụng trong trường hợp nào thì mời bạn đọc tiếp bài viết dưới đây nhé.

Phân trang bằng LIMIT & OFFSET

/articles?limit=10&offset=0

Chắc hẳn url trên khá quen thuộc với mọi người, đây là kĩ thuật phân trang dựa trên limitoffset. Nguyên tắc hoạt động của nó khá đơn giản: limit là giới hạn bản ghi còn offset là bắt đầu lấy dữ liệu sau offset hàng.

Ví dụ trên sẽ lấy 10 hàng bắt đầu từ hàng đầu tiên.

Thể hiện của kĩ thuật phân trang này là một tính năng trông giống như hình bên dưới.

Phân trang dựa trên limit offset

Các trang như 1,2,3... đến 30 được hiển thị, người dùng có thể dễ dàng bấm vào trang muốn xem để xem nội dung trong trang đó.

Về phần xử lý phía máy chủ, hầu hết việc lấy dữ liệu ra theo limitoffset là từ trong cơ sở dữ liệu. Hiện tại hầu như cơ sở dữ liệu nào cũng hỗ trợ cú pháp truy vấn limitoffset. Ví dụ như trong PostgreSQL:

SELECT * FROM articles LIMIT 10 OFFSET 0;

Với mỗi limitoffset người dùng gọi lên thay thế vào câu truy vấn bạn sẽ lấy được kết quả mong muốn.

Trong quá trình người dùng đang lấy dữ liệu liên tục, nếu như thời điểm đó có bản ghi được thêm vào hoặc bị xóa sẽ gây ra hiện tượng trùng lặp hoặc thiếu sót dữ liệu ở trang tiếp theo. Vì bản ghi được thêm sẽ đẩy dữ liệu tiếp theo xuống dưới, còn bản ghi bị xóa thì lại kéo dữ liệu lên.

Một điểm trừ nữa là khi số lượng bản ghi rất lớn, truy vấn theo offset có khả năng bị chậm. Nguyên nhân là do cách cơ sở dữ liệu xử lý offset. Hầu hết truy vấn theo offset phải duyệt qua tất cả các hàng cho đến đủ số lượng offset rồi mới bắt đầu lấy dữ liệu. Ví dụ bạn có offset = 1.000.000 thì nó phải duyệt qua 1 triệu hàng rồi bắt đầu lấy từ hàng 1.000.001.

Tóm lại, offsetlimit phù hợp trong trường hợp mong muốn triển khai nhanh, danh sách phân trang được hiển thị theo số thứ tự, khi đó người dùng nhanh chóng điều hướng đến trang họ muốn. Cần cân nhắc sử dụng kĩ thuật này trên tập dữ liệu lớn vì khi đó hiệu năng khả năng cao là bị ảnh hưởng.

Phân trang bằng Cursor

Bạn đã gặp kiểu phân trang này bao giờ chưa? Chỉ bao gồm hai nút Next và Previous như hình dưới đây.

Phân trang dựa trên cursor

Khả năng cao là đang áp dụng kĩ thuật phân trang bằng cursor. Điều đặc biệt của phương pháp này là không có danh sách số thứ tự trang như kĩ thuật limit, offset bên trên.

Một url phân trang bằng cursor có thể trông giống như thế này:

/articles?cursor=4n5pxq24kp

Nguyên tắc hoạt động của cursor khá đơn giản. Ở lượt truy vấn lấy danh sách lần đầu tiên trả về một cursor, sau đó bạn sử dụng cursor này để lấy dữ liệu trong trang tiếp theo. Cứ như thế cho đến khi cursor không trả về nữa tức là dữ liệu đã hết.

{
    "articles": [...],
    "next_cursor": "4n5pxq24kn",
    "prev_cursor": "4n5pxq24kp",
}

Dễ thấy đối với kĩ thuật này bạn không thể nhảy đến một trang xác định nào, vì "con trỏ" chỉ được trả về sau mỗi lần gọi. Thông thường cursor được mã hóa theo quy tắc mà chỉ máy chủ biết, khi truyền lên nó sẽ giải mã để lấy ra dữ liệu cần thiết bên trong.

Ở phía máy chủ, lệnh truy vấn không dùng LIMITOFFSET, thay vào đó là cách truy vấn "lớn hơn hoặc bằng" (>=) kết hợp với index dữ liệu.

Ví dụ, giả sử con trỏ 4n5pxq24kp được máy chủ mã hóa từ id = 10. Khi lấy trang tiếp theo câu lệnh truy vấn giống như là:

SELECT * FROM articles WHERE id > 10 LIMIT 10;

Dễ thấy, nếu đánh index trên trường id của bảng articles thì câu lệnh không cần phải duyệt qua 10 bản ghi đầu tiên để bỏ qua nữa mà nó lấy luôn dữ liệu đằng sau 10. Độ phức tạp lúc này là O(1).

Phương pháp này còn khắc phục được trường hợp dữ liệu được thêm hoặc xóa trong lúc đang phân trang. Đơn giản vì nó không dựa vào offset để lấy bản ghi tiếp theo mà nó dựa vào phép so sánh. Giả sử bản ghi thứ 10 bị xóa đi thì trang tiếp theo vẫn lấy được đủ 10 bản ghi kể từ bản ghi thứ 10 thay vì thứ 9 nếu áp dụng offset.

Rõ ràng cách tiếp cận này về mặt hiệu suất cao hơn hẳn so với limitoffset, tuy nhiên thời gian triển khai và độ phức tạp có thể cao hơn so với phương pháp thông thường. Người dùng không thể điều hướng đến một trang mong muốn và yêu cầu bạn phải có một trường dữ liệu có thể sắp xếp đã được đánh index.

Tổng kết

Trên đây, tôi vừa trình bày hai kĩ thuật phân trang phổ biến. limit, offset thì đơn giản dễ triển khai tuy nhiên gặp vấn đề về hiệu năng trên tập dữ liệu rất lớn. Cursor thì cho hiệu năng tốt nhưng lại có một vài hạn chế khi sử dụng cùng độ phức tạp cao hơn. Mỗi phương pháp đều thể hiện ra ưu nhược điểm, chúng ta không nhất thiết phải chọn cursor vì hiệu năng cao mà thay vào đó biết cách lựa chọn phương pháp cho phù hợp với bài toán mà bạn đang xử lý.

Cao cấp
Hello

5 bài học sâu sắc

Mỗi sản phẩm đi kèm với những câu chuyện. Thành công của người khác là nguồn cảm hứng cho nhiều người theo sau. 5 bài học rút ra được đã thay đổi con người tôi mãi mãi. Còn bạn? Hãy bấm vào ngay!

Mỗi sản phẩm đi kèm với những câu chuyện. Thành công của người khác là nguồn cảm hứng cho nhiều người theo sau. 5 bài học rút ra được đã thay đổi con người tôi mãi mãi. Còn bạn? Hãy bấm vào ngay!

Xem tất cả

Đăng ký nhận thông báo bài viết mới

hoặc
* Bản tin tổng hợp được gửi mỗi 1-2 tuần, huỷ bất cứ lúc nào.

Bình luận (0)

Nội dung bình luận...
Bấm hoặc cuộn mạnh để sang bài mới