2015-10-20 52 views
0

互聯網上有很多關於JDBC分頁/遍歷巨大結果集的不同教程。 所以,基本上有許多方法,到目前爲止,我發現:(?)JDBC分頁:供應商特定的sql與結果集fetchSize

  1. Vendor specific sql
  2. 滾動結果集
  3. 保持平淡導致內存設置,行只在必要時映射(使用FETCHSIZE)

    結果集獲取大小,無論是明確地設置,或通過默認等於 到語句獲取傳遞給它的大小,確定 多個行,在任何後續的檢索前往該結果集的 數據庫。這包括完成原始查詢所需的仍然爲 的任何行程,以及任何將 數據重新排列到結果集中的行程。可以顯式地或者隱式地重新獲取數據,以更新滾動敏感的或可滾動不敏感/可更新的結果集。

  4. 光標(?)
  5. Custom seek method paging implemented by jooq

對不起,搞亂所有這些,但我需要有人來清除出我。 我有一個簡單的任務,其中服務使用者用pageNumber和pageSize請求結果。貌似我有兩個選擇:

  1. 使用供應商特定的SQL
  2. 保持連接/語句/結果存儲在存儲器設置,並依靠JDBC FETCHSIZE

在後一種情況下,我使用rxJava-jdbc和如果你看producer implementation它擁有結果集,那麼你所做的只是調用請求(long n)並且處理另外n行。當然,一切都隱藏在rxJava的Observable suggar下。我不喜歡這種方法是,你必須在不同的服務調用之間保存resultSet,並且如果客戶忘記耗盡或關閉它,必須清除那個resultSet。 (注意:這裏的resultSet是java ResultSet類,不是實際的數據)

那麼,推薦的分頁方式是什麼?與持有連接相比,供應商特定的sql是否被認爲是慢的?

我使用的是oracle,ScrollableResultSet不建議與巨大的結果集一起使用,因爲它在客戶端緩存整個結果集數據。 proof

回答

1

保持資源無限期地開放通常是一件壞事。例如,數據庫將爲您創建一個遊標以獲取提取的行。該遊標和其他資源將保持打開狀態,直到關閉結果集爲止。並行執行的查詢越多,佔用的資源越多,並且由於資源池耗盡(例如,可以一次打開的遊標數量有限),數據庫將在某個時間拒絕進一步的請求。例如,Hibernate使用供應商特定的SQL來獲取「頁面」,我會這樣做。

+0

謝謝,還沒有想過有限數量的遊標。好點子。 –

1

有許多方法,因爲有許多不同的用例。

您是否確實希望用戶獲取結果集的每一頁?或者,如果他們感興趣的數據不存在,他們更有可能獲取第一或第二頁並嘗試其他內容。例如,如果你是Google,你可以非常自信地看到人們會看第一頁的結果,一小部分看第二頁的結果,一小部分結果來自第三頁。在這種情況下,使用供應商特定的代碼來請求一頁數據並且只有在用戶請求時纔會爲下一頁運行它是非常有意義的。如果您希望用戶獲取結果的最後一頁,另一方面,爲每個頁面運行單獨的查詢將比運行單個查詢並執行多次提取更爲昂貴。

用戶需要多長時間才能保持查詢打開?多少個併發用戶?如果您正在構建一個可供數十個用戶訪問的內部應用程序,並且您希望用戶將遊標保持打開幾分鐘,那可能是合理的。如果您正在嘗試構建一個應用程序,該應用程序將有成千上萬的用戶在幾個小時內對結果進行分頁,那麼保留資源分配是一個好主意。如果你的用戶真的是要獲取數據並儘可能快地在循環中處理數據的機器,那麼帶有多個抓取的單個ResultSet就更有意義了。

重要的是沒有錯過任何一行/每行只有一次被看到/跨頁面的結果是一致的嗎?從單個遊標進行多次提取可以確保結果中的每一行只出現一次。單獨的分頁查詢可能不會 - 在執行查詢之間添加或刪除新數據,您的排序可能不完全確定等。

+0

將會有兩個用例:1.另一個服務將調用一個應用程序併爲每個請求獲取所有數據(數百個 - 依次)(請求產生完全不同的巨大結果集)。 2.其他客戶端應用程序可能只讀取1,2..5頁,但它們很可能會同時執行(數百個請求,而不是數千個)。 Re:最好不要錯過這一行,但行每15分鐘更新一次,所以在這段時間內結果將始終如一。 –

1

ScrollableResultSet在客戶端緩存結果 - 這需要內存資源。但是,例如PostgreSQL在默認情況下並沒有人抱怨。有些數據庫只是使用客戶端的內存來保存整個結果集。在大多數情況下,數據庫必須處理更多的數據才能重新評估查詢。 此外,您通常擁有比數據庫實例更多的客戶端。

另請注意,查詢重新執行 - 使用rownum - 由Hibernate實現並不保證正確(一致)的結果。如果在執行之間修改數據並使用默認隔離級別。

這真的取決於用例。更改Oracle的最大init參數連接和打開遊標需要重新啓動數據庫。 所以ScrollableResultSet和遊標只能用於預測(併發)用戶的數量。

+0

一致性可以保證傳遞WHERE update_ts

+1

您還必須處理刪除的記錄。或者你必須只使用「邏輯」刪除 - 只需將記錄標記爲已刪除。您也可能需要查看第一次執行時的記錄。一致性問題很複雜,通常不值得嘗試。使用更復雜的連接時,重新執行可能會對性能產生重大影響。通常您可能希望爲每個頁面更改查詢的執行計劃。第一頁可以比上一頁更容易返回。對於Oracle來說,一旦使用單個exec,「結果」就更容易了。計劃。 – ibre5041

+0

感謝您的寶貴意見。事實上,我錯過了刪除案例,並錯過了一旦我更新舊記錄,它會將第二頁向下移動一個元素,即使我有WHERE子句。 –