2012-10-30 63 views
11

從我剛纔的問題跟進:如何提供具有1,000,000個數據庫結果的API客戶端?

Using "Cursors" for paging in PostgreSQL

什麼是提供一個API客戶端包含1,000,000個數據庫結果的好辦法?

我們目前正在使用PostgreSQL。一些建議的方法:

  • 使用隨機數使用Cursors
  • 尋呼尋呼(添加「大於ORDER BY」每個查詢)
  • 尋呼使用LIMIT和OFFSET(分解非常大的數據集)
  • 信息保存到一個文件,並讓客戶端下載
  • 通過迭代的結果,然後將POST數據到客戶端服務器
  • 僅返回鍵到客戶端,然後讓客戶端熱曲從Amazon文件等雲文件中獲取對象(仍可能需要分頁才能獲取文件名)。

有什麼我沒有想到的是,這是愚蠢的簡單和方式比這些任何選項更好?

回答

24

表中有一個主鍵。利用它。

而不是LIMITOFFSET,使用主鍵上的過濾器做你的分頁。你在暗示這與您的評論:

尋呼使用隨機數(添加「大於ORDER BY」每個 查詢)

但沒有什麼隨機你應該怎麼做。

SELECT * FROM big_table WHERE id > $1 ORDER BY id ASC LIMIT $2 

允許客戶端指定兩個參數,它看到的最後一個ID和要獲取的記錄數。你的API必須有一個佔位符,額外的參數或者替代呼叫來「獲取第一個 n ID」,它在查詢中省略了WHERE子句,但這很簡單。

此方法將使用相當有效的索引掃描來按順序獲取記錄,通常避免排序或需要遍歷所有跳過的記錄。客戶可以決定一次需要多少行。

這種方法不同於LIMITOFFSET方法中的一種關鍵方式:併發修改。如果INSERT與之間的關鍵字低於而不是某個客戶端已經看到的關鍵字,則此方法根本不會改變其結果,而OFFSET方法將重複一行。同樣,如果您的DELETE行數低於已經看過的ID,則此方法的結果不會更改,而OFFSET將跳過看不見的行。儘管如此,使用生成的關鍵字只能附加表格也沒有區別。

如果您事先知道客戶端需要整個結果集,那麼最有效的方法就是將整個結果集都發送給它們,而不要使用這個分頁業務。這就是我使用遊標的地方。讀取數據庫中的行並將其發送到客戶端的速度與客戶端接受它們的速度一樣快。此API需要設置限制客戶端被允許的速度以避免過多的後端負載;對於慢速客戶端,我可能會切換到分頁(如上所述)或將整個遊標結果暫存到臨時文件並關閉數據庫連接。

重要注意事項

  • 需要一個UNIQUE約束/ UNIQUE索引或PRIMARY KEY可靠
  • 不同併發修改行爲來限制/偏移,參見上文
1

API是否接受從開始的偏移量和要返回的記錄數。這是一種分頁,客戶可以確定在一個頁面請求中返回多少條記錄。 API還應返回查詢可能的記錄總數,以便客戶端知道有多少個「頁面」,或者可選地,它可以在返回的記錄數爲零或小於要求的記錄。您可以在您的SELECT語句中使用OFFSET子句(該記錄開始檢索)和LIMIT子句(返回的記錄數)來控制PostgresSQL查詢中的這一點。

+3

使用的問題OFFSET是它需要服務器在「LIMIT」之前迭代整個結果集,因此它會破壞非常大的數據集。我實際上使用了這樣做的API,並且在大約100,000次結果後我們遇到了重大問題。 –

相關問題