API做翻頁的兩種思路


在開發API的時候,有時候數據太多了,就需要分頁讀取。

基於偏移量的分頁(Offset-based)

這種方式就是會提供一個每頁筆數(page size)來定義返回條目的最大數,提供一個頁數(page number)來表示從哪里開始讀取數據。

例如:

SELECT * FROM "CampusResumes" ORDER BY "Name" DESC LIMIT 5 OFFSET 10;

這句話的意思就是從該表中讀取數據,按照Name字段降序排序,從第10筆數據后開始讀取,一共讀取5筆(可能不足5筆)。

這就相當於page size = 5,page number = 3的分頁讀取。

 

Offset-based分頁方式實現起來非常的簡單,對用戶來說體驗也比較好。但是還有有一些劣勢的:

  • 對於大規模的數據集,效率不夠高。因為數據庫需要進行count和skip操作。
  • 如果數據經常發生變化,那么結果不可信。在查詢的時候如果插入或刪除了數據,那么某條數據可能會出現兩次或者翻頁的時候越界了。
  • 在分布式系統中實現起來略麻煩。這種情況下,你可能需要掃描不同的數據碎片,然后才能得到想要的數據。

總體來說,當允許結果出現誤差的時候,Offset-based分頁還是很好用的。

 

基於游標的分頁(Cursor-based)

為了解決Offset-based分頁的那些問題,可以采用Cursor-based分頁。

這種方式是這樣的:客戶端首先發送請求,請求里提供所需數據的數量。然后服務器響應請求,返回這些數量的數據(如果有這么多數據的話),同時還會返回一個游標(Cursor)。在下一次請求中,客戶端除了發送請求數據的數量之外,還把這個cursor也傳送過去,這個cursor就表示這次所要讀取的數據的開始位置。

這看起來和Offset-based分頁差別不大,但是卻更有效率。數據庫里面的數據可以根據cursor值來獲取。

例如:

SELECT * FROM "CampusResumes" WHERE "Id" > 15 ORDER BY "Id" LIMIT 5;

這個例子里,上次請求返回的cursor(Id字段)值為15,這次要獲取Id比15大的連續的5條數據。

這里的Id字段本身就是一個索引,所以查詢起來非常快。

在這次請求的響應里,可以把本次結果的最后一條的Id作為cursor再返回去:

所以返回的cursor值為23,以供下次讀取。

 

Cursor-based翻頁的優點是:

  • 性能好。因為cursor字段通常都是索引列,查起來很快。
  • 一致性。添加和刪除數據並不影響返回的結果,翻頁時同一筆數據也只會被返回一次。

Cursor-based翻頁通常適用於大量和動態的數據集,但是它也有一些缺點

  • 無法跳轉到指定的頁。Cursor-based翻頁只能一頁一頁遍歷結果。
  • 結果必須基於一個唯一並且順序的字段。不可以讓添加記錄到任意位置。
  • 實現起來比Offset-based復雜一點,尤其對客戶端來說。

對於Cursor字段的選擇:

  • Id,順序的主鍵。
  • 時間戳
  • 加密字符串。它們看起來像隨機字符串,但實際上通常是Cursor里加入了額外的信息。

總體來說Cursor-based翻頁還是更適合於高吞吐的應用,這種情況下客戶端通常需要掃描整個數據集。

 

翻頁的最佳實踐

  • 設定每頁的最大筆數限制。
  • 針對大數據集,盡量不要使用Offset-based分頁。
  • 分頁的默認排序,通常會把新的數據先返回,舊的數據往后翻。
  • 沒分頁的API盡量去實現分頁。
  • 分頁的時候,最好把下一頁的鏈接一同返回,並鼓勵客戶端使用這個鏈接,參考HATEOAS。這樣以后你改變翻頁策略的時候,客戶端不會爆掉。
  • 不要在Cursor里加入敏感信息


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM