3 cách phân trang trong databases thể hiện ở dự án stackoverflow, reddit, facebook và hack news

Nội dung bài viết

Video học lập trình mỗi ngày

Phân trang là một trong những thủ thuật để tối ưu hóa dữ liệu hàng đầu hiện nay. Facebook, reddit đã làm chúng ta mê mẩn đắm chìm trong thế giới của họ, mỗi lần lướt là một quá trình phân trang được thiết kế hoàn hảo. Trong bài này chúng ta sẽ tìm hiểu những thủ thuật đó trong Mongodb.

mongodb pagination

Sơ lược về 3 thuật toán phân trang trong databases

bài trước chúng ta đã bàn luận về chủ đề mà rất nhiều bạn quan tâm đó là: MongoDB Schema Design Best Practices - Tìm hiểu về thiết kế Schema trong Mongodb (1:1, 1:N, N:M). Một chủ đề mà bất cứ những bạn nào mà muốn tìm hiểu về backend (BE) thì khó có thể bỏ qua hoặc không thể không tìm hiểu. Và trong thảo luận đó, chúng ta đã thống nhất lấy một số tình huống thực tế trong đó có vấn đề 1 : N hay còn gọi là lược đồ Một - Nhiều. Cụ thể như sau:

Chúng ta có một status trên facebook hay một bài viết trên blog thì đương nhiên sẽ có nhiều comments tương tác và thảo luận. Nếu bạn là một KOL nổi tiếng thì chắc cũng có hàng trăm ngàn lượt comments con số đó không hề nhỏ. Tương tự như vậy, giả sử một ứng dụng sẽ có nhiều KOLs như vậy thì đồng nghĩa với việc số lượng comments trên mỗi status theo tuyến tính. Chỉ vậy thôi thì database của hệ thống sẽ phình lên, và truy cập dữ liệu sẽ chậm chạp, dẫn đến sự khó chịu cho người dùng. Dó đó, những nhà nghiên cứu phát triển mới cho ra đời thuận toán phân trang.

Cho đến nay thì thuật toán phân trang rất da dạng, nhưng chủ yếu là 3 cách dưới đây, và quan trọng mỗi cách đều có ưu và nhược điểm khác nhau. Giống như việc reddit, google, stackoverflow, hack news đều có phong cách phân trang riêng của họ. Tiếp theo chúng ta sẽ đi tìm hiểu từng cách trên.

Stackoverflow Pagination

Stackoverflow là một cộng đồng DEV mà anh em chúng ta ai cũng đều ghé qua, và giao diện của họ thật đơn giản nhưng thân thiện. Chúng ta hãy cùng xem cách họ phân trang như thế nào? Hay xem hình dưới đây:

stackoverflow Pagination

Cách Stackoverflow phân trang theo kiểu gái nhà lành, nghĩa là theo kiểu truyền thống dựa vào hai phương thức mà hầu như database nào cũng có. Đó là sử dụng skiplimit... Đúng hay sai? Các bạn hãy xem, giả sử tôi tìm search tags nodejs sau đó tôi click vào page thứ 6 thì url sẽ thay đổi.

Ban đầu sẽ là https://stackoverflow.com/questions/tagged/node.js sau đó nếu tôi click vào page = 6 thì url sẽ thay đổi như sau https://stackoverflow.com/questions/tagged/node.js?tab=newest&page=6&pagesize=50. Dựa vào url trên, chúng ta sẽ không khó để đoán được công thức như sau:

    db.stackoverflow.find({
    }).skip((page - 1) * 50).limit(50)

Trong đó được skip = (page - 1) * 50 xem lại bài trước. Về mặt ưu điểm của cách làm này thì chúng ta không bàn tới vì nó quá rõ. Nhưng phần nhược điểm thì có lẽ rất chậm nếu dữ liệu trong database quá nhiều mà không được xé nhỏ... Đương nhiên tôi không nói Stackoverflow là chậm, vì chúng ta không thể múa rìu qua mặt thợ được.

Họ đã làm quá tốt và có lẽ chúng ta sẽ không dám so sánh. Nhưng ở đây chúng ta nên phân tích về nhược điểm này một chút nếu bạn không quá xuất sắc như đội ngũ của họ.

Nhược điểm Khi sử dụng skiplimit. Ví dụ skip=500000limit=1000 thì query đó sẽ phải lấy ra tổng cộng là 500000 + 1000 = 510.000 documents. Sau đó chỉ show lên 1000 docs mà thôi. Tôi sẽ chứng minh điều đó cho hai level khác nhau. lv1 xem như mới tìm hiểu về Mongodb, và lv2 3 4 là đã thành thục Mongodb. OK!

Level 1 thì các bạn xem lại bài Cách phân trang trong javascript nâng cao. Chúng ta sẽ xem và hiểu.

level 2 thì chúng ta sử dụng Mongo Shell để phát hiện điều đó.

Hack news Pagination

Hack news là một trong số cộng đồng mà tôi đã gợi ý cho các bạn trong bài viết trước đó có tên 10 websites giúp Developers kiếm lương x3 rất OK. Bạn có thể quay lại bài đó để biết thêm những trang web và có nhiều lập trình viên thường lui tới, để tham khảo và tìm hiểu công nghệ mới trong đó.

Hack news Pagination

Quay trở lại với việc Pagination trong hack news thì chúng ta có thể hình dung giữa Stackoverflowhack news có điểm giống nhau đó là cũng phân trang theo cách sử dụng skiplimit nhưng điểm khác biệt ở đây chính là cách bố trí cách người dùng muốn chuyển sang trang tiếp theo. Hãy xem xét...

Đầu tiên chúng ta xem ở đây hack news chỉ giới hạn là 30 documents 1 page. Và nếu muốn xem trang thứ 2 thì bạn sẽ phải click vào xem thêm, cứ như thế bạn sẽ đi lần lượt đến trang 99 với click 99 lần, nếu như các bạn không save lại url. và quan trọng hơn nữa chúng ta hãy để ý url của họ thay đổi như thế nào so với stackoverflow.

Mới vào thì url sẽ có dạng sau. https://news.ycombinator.com/newest và khi chúng ta thử click vào More button thì url sẽ thay đổi thành https://news.ycombinator.com/newest?next=31525594&n=31. Điều này cho ta thấy gì ở đây. Đó chính là một tham số next=31525594n=31. Với n=31 thì chúng ta có thể dễ đoán đó chính là số records đã hiện thị, cứ như thế các lần tiếp theo tôi đoán là 61, 91...

Thử nghiệm xong thì tôi đã đúng. Câu hỏi ở đây là next=31525594 là gì? Và nó giữ vai trò gì ở đây. Vâng, đó chính là sự khác biệt giữa stackoverflowhack news.

Họ đã lấy một index để query và không sử dụng tính năng skip do đó hiệu quả nhanh hơn nhiều. Câu lệnh có lẽ như thế này.

    // nếu page = 1, thì có lẽ next sẽ underfined or = 0 ví dụ
    db.hacknews.find({
        next: {$gt: 0}
    }).limit(30) 

    // nếu page = 2 thì next sẽ có giá trị như chúng ta ghi ở trên
    db.hacknews.find({
        next: {$gt: 31525594}
    }).limit(30)

Tương tự như vậy chúng ta sẽ có tham số next=??? cho mỗi trang tiếp theo... rất hay. Cách này rất tối ưu hóa dữ liệu, khi muốn lấy 30 thì nó chỉ lấy 30 mà thôi. Tuyệt vời phải không, nhưng có nhược điểm không. Suy nghĩ 3 giây.... ... ... Có, nó có nhược điểm.

Như tôi đã nói ở trên thì bạn muốn lấy page=99 thì bạn phải biết next=??? của page=98... Vậy làm sao để biết được... Đó chính là nhược điểm, chúng ta không tự chuyển tiếp từ page=2 sang page=99 một cách nhanh chóng giống như stackoverflow được ngoài cách phải click 99 lần.

Tất nhiên trên đây là chúng ta bàn luận và phỏng đoán theo mỗi kiểu khác nhau. Có thể dữ liệu và cách triển khai của họ không giống như chúng ta nghĩ. Nhưng 2 cách trên cũng là mẫu hình cho chúng ta tham khảo để triển khai hợp lý cho mỗi ứng dụng của mình. Chưa hết còn cách thứ 3, cách mà facebook, reddit, instagram đang làm điều đó... Tiếp tục

Reddit Pagination

Có thể bạn đã bị missing