日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

SELECT语句使用JDBC和Hibernate批量获取

發布時間:2023/12/3 编程问答 51 豆豆
生活随笔 收集整理的這篇文章主要介紹了 SELECT语句使用JDBC和Hibernate批量获取 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

介紹

現在,我已經介紹了Hibernate對INSERT , UPDATE和DELETE語句的批處理支持,是時候分析SELECT語句結果集的批量提取了。

JDBC ResultSet提供了一個客戶端代理游標,用于獲取當前語句的返回數據。 執行該語句后,必須將結果從數據庫游標傳輸到客戶端。 此操作可以立即執行,也可以根據需要執行。

ResultSet游標有三種類型 :

游標類型 描述
TYPE_FORWARD_ONLY 這是默認的ResultSet游標類型。 結果集只能向前移動,并且結果數據可以一次獲取,也可以在迭代游標時檢索。 數據庫可以決定在查詢開始時還是在獲取時獲取可用的數據。
TYPE_SCROLL_INSENSITIVE 可以向前和向后滾動結果集,并且結果數據對游標仍處于打開狀態時發生的并發更改不敏感
TYPE_SCROLL_SENSITIVE 可以向前和向后滾動結果集,并且結果數據對在游標仍處于打開狀態時發生的并發更改敏感 。 因此,數據是按需獲取的,而不是從數據庫游標緩存中獲取的


并非所有數據庫驅動程序都實現所有游標類型,并且批處理獲取行為是通過JDBC語句 fetchSize屬性控制的,根據Javadoc :

當此Statement生成的ResultSet對象需要更多行時,向JDBC驅動程序提供有關應該從數據庫中獲取的行數的提示。 如果指定的值為零,則忽略提示。 默認值為零。

因此,默認的獲取策略是特定于數據庫的,從應用程序性能的角度來看,這方面在調整數據訪問層時非常重要:

  • 甲骨文

    默認情況下, Oracle JDBC運行查詢時,它一次從數據庫游標中檢索10行的結果集。根據Oracle JDBC驅動程序文檔 :“合理的”取決于應用程序的詳細信息。 Oracle建議fetchSize不超過100,盡管在某些情況下可能更合適。 對于某些查詢,即使返回許多行, fetchSize可能也會過大。
  • 的MySQL

    默認情況下, 結果集是完全檢索和存儲在內存中。 在大多數情況下,這是最有效的操作方式,并且由于MySQL網絡協議的設計,因此更易于實現。
  • SQL服務器

    通常,當用于SQL Server的Microsoft JDBC驅動程序執行查詢時,驅動程序會將所有結果從服務器檢索到應用程序內存中。 盡管這種方法最大程度地減少了SQL Server上的資源消耗,但它可以在JDBC應用程序中引發產生非常大結果的查詢的OutOfMemoryError 。
  • PostgreSQL的

    默認情況下,驅動程序會立即收集查詢的所有結果。 這對于大型數據集可能很不方便,因此JDBC驅動程序提供了一種將ResultSet基于數據庫游標并且僅獲取少量行的方法。
  • DB2

    默認情況下,驅動程序會立即收集查詢的所有結果。 這對于大型數據集可能很不方便,因此JDBC驅動程序提供了一種將ResultSet基于數據庫游標并且僅獲取少量行的方法。 fetchSize屬性與queryDataSize屬性不同。 fetchSize影響返回的行數,而queryDataSize影響返回的字節數。

    例如,如果結果集大小為50 KB,而queryDataSize的值為32767(32KB),則需要兩次到數據庫服務器的行程才能檢索結果集。 但是,如果將queryDataSize設置為65535(64 KB),則只需一趟數據源即可檢索結果集。

Java Persistence Query接口通過Query.getResultList()方法調用僅提供全結果檢索。

Hibernate還通過其特定的Query.scroll() API支持可滾動的ResultSet游標。

可滾動的ResultSets唯一明顯的優點是,由于可以按需獲取數據,因此我們可以避免客戶端的內存問題。 這聽起來似乎是很自然的選擇,但實際上,由于以下原因,您不應該獲取大型結果集:

  • 結果集較大會占用大量數據庫服務器資源,并且由于數據庫是高度并發的環境 ,因此可能會妨礙可用性和可伸縮性
  • 表的大小趨于增長,適度的結果集可能很容易變成很大的表。 這種情況發生在生產系統中,很早就發布了應用程序代碼。 由于用戶只能瀏覽整個結果集中的一小部分,因此分頁是一種更具可伸縮性的數據提取方法
  • 過于常見的偏移分頁不適用于大型結果集(因為響應時間隨頁碼線性增加),并且在遍歷大型結果集時應考慮鍵集分頁 。 鍵集分頁提供了恒定的響應時間 ,對正在獲取的頁面的相對位置不敏感
  • 即使對于批處理作業 ,將處理項目限制為適當的批處理大小總是比較安全的。 大批量可能導致內存問題或導致長時間運行的事務,從而增加了撤消/重做事務日志的大小

測試時間

我們的域實體模型如下所示:

以下測試將用于驗證各種結果集的獲取行為:

@Test public void testFetchSize() {doInTransaction(session -> {int batchSize = batchSize();for(int i = 0; i < itemsCount(); i++) {Post post = new Post(String.format("Post no. %d", i));int j = 0;post.addComment(new Comment(String.format("Post comment %d:%d", i, j++)));post.addComment(new Comment(String.format("Post comment %d:%d", i, j++)));session.persist(post);if(i % batchSize == 0 && i > 0) {session.flush();session.clear();}}});long startNanos = System.nanoTime();LOGGER.info("Test fetch size");doInTransaction(session -> {List posts = session.createQuery("select p " +"from Post p " +"join fetch p.comments ").list();LOGGER.info("{}.fetched {} entities",getClass().getSimpleName(),posts.size());});LOGGER.info("{}.testFetch took {} millis",getClass().getSimpleName(),TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - startNanos)); }

要將Hibernate配置為使用顯式Statement fetchSize ,我們需要設置以下Hibernate屬性:

properties.put("hibernate.jdbc.fetch_size", fetchSize());

每個測試將插入5000個Post實體,每個實體具有2個Comment 。

針對商業數據庫運行第一個測試,結果如下:

提取大小 持續時間[毫秒]
1個 1190
10 640
100 481
1000 459
10000 449
默認值(10) 545


提取大小越大,則提取整個結果集所需的往返行程越少。 如果返回的行包含許多列,則較大的訪存大小將按比例需要較大的數據庫緩沖區。

第二輪測試針對PostgreSQL 9.4運行,結果如下:

提取大小 持續時間[毫秒]
1個 1181
10 572
100 485
1000 458
10000 437
默認(全部) 396


即使fetchSize等于要返回的總行數,默認的fetch大小也會產生最佳結果。 由于沒有上限緩沖區限制,因此在檢索大型結果集時,默認的提取大小可能會導致OutOfMemoryError問題。

結論

雖然大多數數據庫服務都不會對結果集的獲取大小施加默認上限,但是最好限制整個結果集(如果要求允許的話)。 大小有限的結果集應解決無限制的獲取大小缺陷,同時即使在查詢的數據逐漸增長的情況下,也要確保可預測的響應時間。 查詢越短,行級鎖被釋放的越快,數據訪問層的可伸縮性就越高 。

  • 代碼可在GitHub上獲得 。

翻譯自: https://www.javacodegeeks.com/2015/04/select-statements-batch-fetching-with-jdbc-and-hibernate.html

總結

以上是生活随笔為你收集整理的SELECT语句使用JDBC和Hibernate批量获取的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。