API作翻頁的兩種思路

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

基於偏移量的分頁(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分頁。blog

這種方式是這樣的:客戶端首先發送請求,請求裏提供所需數據的數量。而後服務器響應請求,返回這些數量的數據(若是有這麼多數據的話),同時還會返回一個遊標(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里加入敏感信息
相關文章
相關標籤/搜索