Phân Trang Dựa Trên Con Trỏ Là Gì? Token và Sự Đánh Đổi

Phân Trang Dựa Trên Con Trỏ Là Gì? Token và Sự Đánh Đổi

Trình duyệt Agent Scrapeless cho phép quá trình tự động của bạn điều hướng qua các giao diện kết quả động trong khi ứng dụng của bạn theo dõi trạng thái phân trang và các bản ghi đã thu thập.

Tóm tắt ngắn gọn

  • Một con trỏ xác định một vị trí tiếp tục. Bạn chưa cung cấp nội dung cần dịch. Hãy gửi đoạn tiếng Anh bạn muốn dịch sang tiếng Việt (giữ nguyên mọi Markdown/HTML và token đặc biệt), tôi sẽ dịch theo đúng quy tắc bạn nêu.
  • Thứ tự ổn định cần một bộ phân xử ràng buộc (deterministic tie-breaker). Một dấu thời gian một mình có thể không phân biệt được các bản ghi được tạo cùng một lúc.
  • Phân trang con trỏ không ngụ ý một ảnh chụp (snapshot). Các thao tác chèn, xóa và cập nhật đồng thời vẫn phụ thuộc vào hợp đồng tính nhất quán của dịch vụ.
  • Một checkpoint bao gồm truy vấn cũng như con trỏ. Lưu trữ bản ghi trước khi tiến tới trạng thái tiếp tục đã cam kết.

Một Con trỏ Tiếp tục Một Truy vấn Có Thứ Tự Cụ Thể

Phân trang dựa trên con trỏ chia một tập kết quả thành các trang và cung cấp cho client một vị trí để tiếp tục. Thay vì yêu cầu máy chủ bỏ qua một số lượng bản ghi được đánh số, client trả về một giá trị tiếp tục từ phản hồi trước đó. Máy chủ diễn giải giá trị đó trong khuôn khổ các quy tắc sắp xếp và lọc của truy vấn. Do đó, con trỏ chỉ có ý nghĩa trong mối tương quan với quá trình duyệt một tập hợp cụ thể.

Từ cursor không quy định một tên tham số hay cấu trúc dữ liệu mang tính chuẩn chung. Một REST API có thể cung cấp một token trang kế tiếp hoặc một liên kết tiếp theo, trong khi một kết nối GraphQL có thể cung cấp các cursor của edge và thông tin trang. Hãy đọc hợp đồng của API đã chọn trước khi xây dựng một vòng lặp. Một client đoán rằng có một tham số tên là cursor có thể gửi một yêu cầu HTTP hợp lệ mà dịch vụ sẽ diễn giải khác với thao tác phân trang mà bạn dự định.

Hướng dẫn page-token AIP-158 xem token trang như các khối bất khả tri và ràng buộc phần tiếp theo với các tham số yêu cầu khác. Thiết kế đó giúp client độc lập với cách biểu diễn nội bộ của backend. Token có thể mã hóa một vị trí, tham chiếu đến trạng thái phía máy chủ hoặc chứa các chi tiết truy vấn được bảo vệ. Hình thức của nó không thể chứng minh được dịch vụ sử dụng cơ chế nào, và một client không nên cần đến hiểu biết đó để tiếp tục một cách chính xác.

Tại Sao Thứ Tự Tất Định Lại Quan Trọng

Thứ tự xác định (deterministic) gán cho mỗi bản ghi một vị trí được xác định rõ ràng so với ranh giới tiếp tục. Sắp xếp theo một dấu thời gian không duy nhất có thể khiến nhiều bản ghi bị ràng buộc cùng nhau ở rìa của một trang. Một thiết kế keyset điển hình sẽ thêm một định danh duy nhất bất biến vào thứ tự sắp xếp, để ranh giới tham chiếu đến một khóa sắp xếp hoàn chỉnh. Lựa chọn cụ thể phụ thuộc vào cơ sở dữ liệu và mô hình dữ liệu của ứng dụng.

Hãy xem xét một nguồn cấp giả định được sắp xếp theo thời gian tạo và ID bản ghi. Trang tiếp theo bắt đầu sau cặp cuối cùng trên trang hiện tại, sử dụng cùng hướng sắp xếp. Nếu nhiều bản ghi có cùng thời gian tạo, ID sẽ quyết định bản ghi nào đã được truy cập. Đây là một ví dụ mang tính khái niệm hơn là mô tả về một endpoint của Scrapeless hoặc một cam kết về một kế hoạch thực thi cơ sở dữ liệu cụ thể.

The Hướng dẫn sắp xếp trong PostgreSQL giải thích lý do tại sao các kết quả truy vấn giới hạn cần một thứ tự có thể dự đoán được và tại sao các hàng bị bỏ qua bởi offset vẫn cần công việc trên máy chủ. Một chỉ mục phù hợp có thể hỗ trợ tra cứu keyset hiệu quả, nhưng phân trang bằng cursor tự nó không chứng minh rằng chỉ mục đó tồn tại. Hãy kiểm tra kế hoạch truy vấn thực tế khi đánh giá một backend mà bạn vận hành; đừng suy ra tốc độ chỉ từ tên tham số của API.

Con trỏ, Offset và Keyset Là Các Thuật Ngữ Có Liên Quan

Phân trang theo offset xác định một vị trí bằng số hàng cần bỏ qua, trong khi cursor xác định ranh giới tiếp tục thông qua hợp đồng token của dịch vụ. Phân trang kiểu keyset là một kỹ thuật cơ sở dữ liệu phổ biến để triển khai ranh giới đó bằng các giá trị trường được sắp xếp. Một API có thể cung cấp một cursor mờ đục trong khi sử dụng một phương pháp nội bộ khác. Hãy tách biệt giao diện công khai và thuật toán lưu trữ khi đánh giá các tuyên bố về hiệu năng.

Phân trang theo offset có thể hỗ trợ điều hướng bằng số trang quen thuộc và chuyển trực tiếp đến một offset đã chọn. Duyệt bằng cursor thường ưu tiên tiếp tục tuần tự và có thể không hỗ trợ nhảy đến một trang tùy ý. Cả hai giao diện đều không tự động cung cấp tổng số chính xác với chi phí thấp. Các yêu cầu sản phẩm như nhảy đến trang hai mươi, giữ nguyên một vị trí đã lưu hoặc duyệt ngược lại nên được đánh giá dựa trên hành vi API đã được ghi nhận thay vì mặc định cho rằng chúng được hỗ trợ.

Tính năngĐộ lệchCon trỏ
Vị tríBỏ qua số tiền hoặc số trangVị trí hoặc liên kết do máy chủ cung cấp
Nhảy trực tiếpThường được hỗ trợ trong giới hạnChỉ khi dịch vụ hỗ trợ chúng
Thay đổi dữ liệuVị trí có thể thay đổiPhụ thuộc vào thứ tự và tính nhất quán
Trạng thái máy kháchTruy vấn và vị trí trangTruy vấn và opaque cursor

Các kết nối GraphQL xác định một hợp đồng cụ thể

The Đặc tả Kết nối Con trỏ GraphQL định nghĩa các cấu trúc connection và edge, các tham số phân trang xuôi và ngược, và thông tin trang. Trong mô hình đó, cursor thuộc về các edge và thông tin trang mô tả việc có còn edge nào khác hay không. Những tên trường đó là quy ước của đặc tả đó, không phải là các tên bắt buộc cho mọi API sử dụng cursor.

Duyệt tiến thường sử dụng kích thước trang cùng với con trỏ *after*; duyệt lùi sử dụng ranh giới *before* tương ứng. Đặc tả connection yêu cầu thứ tự của các edge phải được giữ nhất quán giữa hai hướng đó. Một người dùng khi di chuyển lùi không nên nhận được một sự đảo ngược không giải thích được của thứ tự nghiệp vụ của bộ sưu tập. Các triển khai và client cần thống nhất với nhau về việc đang nói đến thứ tự hiển thị hay hướng duyệt.

Sử dụng điều kiện kết thúc được ghi trong tài liệu thay vì ước lượng chỉ từ độ dài trang. Một số API có thể trả về ít mục hơn số được yêu cầu nhưng vẫn cung cấp khả năng tiếp tục. Những API khác định nghĩa trang cuối cùng thông qua việc thiếu token hoặc cờ tiếp tục là false. Một phản hồi không có bản ghi hiển thị cũng cần được diễn giải cẩn thận: quyền truy cập, bộ lọc và hành vi phân trang cụ thể của endpoint có thể ảnh hưởng đến việc trang đó thực sự biểu thị điều gì.

Con trỏ không thể “đóng băng” một tập dữ liệu đang thay đổi

Phân trang dựa trên con trỏ không tự động cung cấp cho tất cả các trang cùng một snapshot cơ sở dữ liệu. Dịch vụ có thể đánh giá từng trang dựa trên dữ liệu hiện tại. Bản ghi mới có thể xuất hiện trước ranh giới tiếp tục, các bản ghi hiện có có thể bị xóa, và các trường sắp xếp có thể thay đổi có thể đẩy một bản ghi sang phía bên kia ranh giới. Việc các thay đổi đó gây ra thiếu sót hay lặp lại quan sát phụ thuộc vào cách triển khai và chính sách nhất quán của nó.

Đối với xuất dữ liệu lịch sử, hãy tìm snapshot, job xuất dữ liệu hoặc ranh giới trên ổn định được ghi trong tài liệu. Đối với luồng dữ liệu trực tiếp, hãy xác định rõ mục tiêu là liệt kê một tập đối tượng cố định hay quan sát các mục hiện tại. Đó là những nhiệm vụ khác nhau. Một “mốc nước cao” có thể giúp mô tả phạm vi thu thập, nhưng chỉ nên dùng khi nguồn hỗ trợ các đảm bảo cần thiết về sắp xếp và lọc.

Giữ lại định danh bản ghi ở phía đích để có thể nhận diện các lần quan sát lặp lại. Khử trùng lặp có thể ngăn các dòng trùng nhau, nhưng không thể chứng minh rằng không có bản ghi nào chưa thấy đã bị bỏ sót. Hãy báo cáo phạm vi bao phủ bằng tín hiệu hoàn tất rõ ràng của nguồn và ranh giới truy vấn của phiên thu thập. Việc duyệt hết giao diện và việc có một kiểm kê lịch sử đầy đủ không phải lúc nào cũng là những tuyên bố tương đương.

Giữ nguyên bộ lọc và ghi checkpoint một cách cẩn trọng

Một continuation token nên đi kèm với truy vấn đã tạo ra nó. Lưu một “dấu vân tay” truy vấn bao phủ tập dữ liệu, bộ lọc, thứ tự sắp xếp và các tham số liên quan khác. Nếu người dùng thay đổi bộ lọc, hãy bắt đầu một lượt duyệt mới trừ khi dịch vụ ghi rõ hỗ trợ kết hợp token cũ với truy vấn mới. Hãy coi một token không hợp lệ là vấn đề hợp đồng cần điều tra, không phải bằng chứng rằng tập dữ liệu trống.

Ghi nhận các bản ghi của trang trước khi ghi nhận trạng thái tiếp tục tiếp theo. Checkpoint nên mô tả những gì đã thực sự được ghi vào bộ nhớ bền vững. Bao gồm số bản ghi đã chấp nhận, định danh trang cuối cùng đã hoàn tất (nếu có), và việc nguồn có báo cáo còn dữ liệu hay không. Giữ các giá trị token nhạy cảm tránh khỏi log dùng chung; một token mờ vẫn có thể chứa thông tin ngay cả khi client được yêu cầu không soi chiếu nó.

Thời hạn sống của token cũng quan trọng. Token lưu trạng thái phía server có thể hết hạn, và token tự chứa có thể gắn với ngữ cảnh ủy quyền hoặc chính sách ký. Hãy đọc kỹ thời gian lưu giữ được ghi trong tài liệu trước khi lập kế hoạch cho một đợt xuất dữ liệu dài. Tiêu chuẩn SCIM cursor pagination minh họa một hợp đồng con trỏ tiêu chuẩn hóa cụ thể, bao gồm các thuộc tính tiếp tục; các quy tắc của nó không nên được áp đặt lên các API không liên quan.

Giao diện trình duyệt có thể ẩn con trỏ bên dưới

Nút “tải thêm” hoặc danh sách cuộn vô hạn có thể dùng con trỏ nội bộ mà không hiển thị con trỏ đó trong URL trang. Tương tác mà bạn thấy là giao diện phân trang của trình duyệt, trong khi các yêu cầu mạng mang dữ liệu tiếp tục. Hãy bắt đầu với hành vi mà trang và ủy quyền của bạn cho phép. Đừng tự tạo token nội bộ hoặc giả định rằng một endpoint không được ghi trong tài liệu là một hợp đồng công khai ổn định.

Scrapeless Agent Browser có thể cung cấp môi trường trình duyệt cho một tác vụ điều hướng kết quả đã được ủy quyền. Hãy dùng các khái niệm Agent Browser để hiểu môi trường đó và các mẫu phân trang trình duyệt để phân biệt các kiểu điều hướng hiển thị. Bộ thu thập vẫn cần định danh bản ghi, phạm vi duyệt được giới hạn, và điều kiện dừng rõ ràng.

Xem lại giá của Scrapeless khi ước tính chi phí phiên, nhưng hãy đánh giá chất lượng tập dữ liệu độc lập với thời lượng phiên. Một phiên thu thập danh mục giả định có thể ghi lại từng ID sản phẩm hiển thị sau khi trang thêm thẻ mới và dừng khi giao diện báo hiệu đã kết thúc. Quy trình đó có thể kiểm chứng việc duyệt trình duyệt đã quan sát được mà không tuyên bố có snapshot giao dịch của danh mục bên dưới.

Chọn phân trang bằng con trỏ cho đúng nhu cầu

Phân trang bằng con trỏ hữu ích khi việc truy cập tuần tự vào một tập được sắp xếp phù hợp với yêu cầu sản phẩm. Nó có thể tránh chi phí offset lớn trong một thiết kế backend phù hợp và có thể diễn đạt ranh giới tiếp tục ổn định rõ ràng hơn số trang. Nó kém thuận tiện hơn khi người dùng cần nhảy tự do giữa các trang hoặc khi một bản xuất bền vững phải tồn tại lâu hơn thời hạn sống của token.

Hãy đánh giá đồng thời thứ tự truy vấn, hợp đồng tiếp tục, dấu hiệu kết thúc, thời hạn sống token và hành vi nhất quán. Ghi các quyết định đó vào tiêu chí chấp nhận của bên tiêu thụ trước khi mở rộng việc thu thập. Chất lượng của tập dữ liệu cuối cùng phụ thuộc vào tất cả các yếu tố đó. Xử lý đúng một token mờ chỉ là một phần của quá trình duyệt tin cậy, trong khi ủy quyền, lưu trữ và phạm vi bao phủ vẫn là trách nhiệm của ứng dụng xung quanh.

Kết luận

Hãy coi con trỏ là trạng thái tiếp tục cho một truy vấn có thứ tự, giữ nguyên các điều kiện kết thúc của dịch vụ, và ghi lưu trữ trước khi tiến lên. Phân trang bằng con trỏ có thể hỗ trợ truy cập tuần tự hiệu quả, nhưng một tập dữ liệu có thể bảo vệ được còn cần một ranh giới nhất quán rõ ràng. Hãy thiết lập ranh giới đó trước khi tuyên bố một lượt duyệt dài là hoàn tất.

Xây dựng quy trình dữ liệu web của bạn

Sử dụng Agent Browser cho điều hướng động trong khi bộ thu của bạn ghi lại trạng thái phân trang và kiểm tra phạm vi bao phủ của tập dữ liệu.

Đăng ký ngay hôm nay và nhận $5 tín dụng miễn phí — không cần thẻ tín dụng.

Nhận $5 tín dụng của bạn →

Câu hỏi thường gặp

Phân trang dựa trên con trỏ có giống phân trang keyset không?

Phân trang dựa trên cursor không nhất thiết giống hệt phân trang dựa trên keyset. Cursor là giao diện tiếp tục (continuation interface) của API, trong khi phân trang keyset là một kỹ thuật cơ sở dữ liệu thường được dùng để triển khai nó. Token có thể ẩn các cơ chế backend khác, vì vậy hãy đánh giá hiệu suất dựa trên bằng chứng từ phần triển khai chứ không chỉ từ giao diện.

Client có thể giải mã một cursor mờ đục (opaque) không?

Client nên xử lý một cursor mờ đục như một giá trị không được diễn giải. Ngay cả khi nội dung của nó có vẻ có thể đọc được, việc giải mã và tự tạo bản thay thế sẽ tạo ra sự phụ thuộc vào các chi tiết nội bộ không được ghi lại. Hãy trả lại token chính xác như API mô tả và giữ nguyên các thiết lập truy vấn liên quan.

Phân trang bằng cursor có ngăn chặn hoàn toàn mọi bản ghi trùng lặp hoặc bị thiếu không?

Phân trang bằng cursor không ngăn chặn hoàn toàn mọi bản ghi trùng lặp hoặc bị thiếu. Dữ liệu có thể thay đổi và tính nhất quán theo từng request vẫn có thể ảnh hưởng đến quá trình duyệt. Hãy dùng sắp xếp quyết định (deterministic ordering), các ranh giới snapshot được ghi lại khi có, và lưu lại danh tính bản ghi vào storage, đồng thời báo cáo rõ các giới hạn nhất quán thực tế của lần thu thập.

Phân trang bằng cursor có thể nhảy trực tiếp đến bất kỳ trang nào không?

Phân trang bằng cursor chỉ hỗ trợ nhảy tới trang bất kỳ khi dịch vụ cung cấp khả năng đó. Nhiều giao diện cursor được thiết kế cho việc duyệt tuần tự. Một sản phẩm cần chọn trang trực tiếp nên xác nhận khả năng điều hướng của API trước khi chọn giao diện hoặc hứa hẹn hành vi đó.

Những gì thuộc về một checkpoint phân trang?

Một checkpoint phân trang nên bao gồm trạng thái tiếp tục đã được commit và định nghĩa truy vấn đã tạo ra nó. Cũng hãy ghi lại tiến độ ghi vào storage và tín hiệu hoàn tất từ nguồn dữ liệu. Chỉ tiến checkpoint sau khi các bản ghi được chấp nhận đã được lưu, và bảo vệ các giá trị cursor nếu chúng có thể làm lộ ngữ cảnh truy vấn nhạy cảm.

Tài liệu tham khảo