表中有一個主鍵。利用它。
而不是LIMIT
和OFFSET
,使用主鍵上的過濾器做你的分頁。你在暗示這與您的評論:
尋呼使用隨機數(添加「大於ORDER BY」每個 查詢)
但沒有什麼隨機你應該怎麼做。
SELECT * FROM big_table WHERE id > $1 ORDER BY id ASC LIMIT $2
允許客戶端指定兩個參數,它看到的最後一個ID和要獲取的記錄數。你的API必須有一個佔位符,額外的參數或者替代呼叫來「獲取第一個 n ID」,它在查詢中省略了WHERE
子句,但這很簡單。
此方法將使用相當有效的索引掃描來按順序獲取記錄,通常避免排序或需要遍歷所有跳過的記錄。客戶可以決定一次需要多少行。
這種方法不同於LIMIT
和OFFSET
方法中的一種關鍵方式:併發修改。如果INSERT
與之間的關鍵字低於而不是某個客戶端已經看到的關鍵字,則此方法根本不會改變其結果,而OFFSET
方法將重複一行。同樣,如果您的DELETE
行數低於已經看過的ID,則此方法的結果不會更改,而OFFSET
將跳過看不見的行。儘管如此,使用生成的關鍵字只能附加表格也沒有區別。
如果您事先知道客戶端需要整個結果集,那麼最有效的方法就是將整個結果集都發送給它們,而不要使用這個分頁業務。這就是我將使用遊標的地方。讀取數據庫中的行並將其發送到客戶端的速度與客戶端接受它們的速度一樣快。此API需要設置限制客戶端被允許的速度以避免過多的後端負載;對於慢速客戶端,我可能會切換到分頁(如上所述)或將整個遊標結果暫存到臨時文件並關閉數據庫連接。
重要注意事項:
- 需要一個
UNIQUE
約束/ UNIQUE
索引或PRIMARY KEY
可靠
- 不同併發修改行爲來限制/偏移,參見上文
使用的問題OFFSET是它需要服務器在「LIMIT」之前迭代整個結果集,因此它會破壞非常大的數據集。我實際上使用了這樣做的API,並且在大約100,000次結果後我們遇到了重大問題。 –