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

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

jdbc select语句_SELECT语句使用JDBC和Hibernate批量获取

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

jdbc select語句

介紹

現(xiàn)在,我已經(jīng)介紹了Hibernate對INSERT , UPDATE和DELETE語句的批處理支持,是時候分析SELECT語句結(jié)果集的批量提取了。

JDBC ResultSet提供了一個客戶端Proxy游標(biāo),用于獲取當(dāng)前語句的返回數(shù)據(jù)。 執(zhí)行該語句后,必須將結(jié)果從數(shù)據(jù)庫游標(biāo)傳輸?shù)娇蛻舳恕?該操作可以立即執(zhí)行,也可以根據(jù)需要執(zhí)行。

ResultSet游標(biāo)有三種類型 :

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


并非所有數(shù)據(jù)庫驅(qū)動程序都實現(xiàn)所有游標(biāo)類型,并且批處理獲取行為是通過JDBC語句 fetchSize屬性控制的,根據(jù)Javadoc :

當(dāng)此Statement生成的ResultSet對象需要更多行時,向JDBC驅(qū)動程序提供有關(guān)應(yīng)從數(shù)據(jù)庫中獲取的行數(shù)的提示。 如果指定的值為零,則忽略提示。 默認值為零。

因此,默認的獲取策略是特定于數(shù)據(jù)庫的,并且從應(yīng)用程序性能的角度來看,這方面在調(diào)整數(shù)據(jù)訪問層時非常重要:

  • Oracle

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

    默認情況下, 結(jié)果集是完全檢索和存儲在內(nèi)存中。 在大多數(shù)情況下,這是最有效的操作方式,并且由于MySQL網(wǎng)絡(luò)協(xié)議的設(shè)計,因此更易于實現(xiàn)。
  • SQL服務(wù)器

    通常,當(dāng)用于SQL Server的Microsoft JDBC驅(qū)動程序執(zhí)行查詢時,驅(qū)動程序會將所有結(jié)果從服務(wù)器檢索到應(yīng)用程序內(nèi)存中。 盡管這種方法最大程度地減少了SQL Server上的資源消耗,但它可以在JDBC應(yīng)用程序中引發(fā)產(chǎn)生非常大結(jié)果的查詢的OutOfMemoryError 。
  • PostgreSQL

    默認情況下,驅(qū)動程序一次收集查詢的所有結(jié)果。 這對于大型數(shù)據(jù)集可能會很不方便,因此JDBC驅(qū)動程序提供了一種將ResultSet基于數(shù)據(jù)庫游標(biāo)并且僅獲取少量行的方法。
  • DB2

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

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

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

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

可滾動的ResultSets唯一明顯的優(yōu)點是,由于可以按需獲取數(shù)據(jù),因此可以避免客戶端的內(nèi)存問題。 這聽起來似乎是很自然的選擇,但實際上,由于以下原因,您不應(yīng)該獲取大型結(jié)果集:

  • 大型結(jié)果集會占用大量數(shù)據(jù)庫服務(wù)器資源,并且由于數(shù)據(jù)庫是高度并發(fā)的環(huán)境 ,因此可能會妨礙可用性和可伸縮性
  • 表的大小趨于增長,適度的結(jié)果集可能很容易變成很大的表。 這種情況發(fā)生在生產(chǎn)系統(tǒng)中,很早就發(fā)布了應(yīng)用程序代碼。 因為用戶只能瀏覽整個結(jié)果集中的一小部分,所以分頁是一種更具可伸縮性的數(shù)據(jù)提取方法
  • 過于常見的偏移分頁不適用于大型結(jié)果集(因為響應(yīng)時間隨頁碼線性增加),并且在遍歷大型結(jié)果集時應(yīng)考慮鍵集分頁 。 鍵集分頁提供了恒定的響應(yīng)時間 ,對所獲取頁面的相對位置不敏感
  • 即使對于批處理作業(yè) ,將處理項目限制為適當(dāng)?shù)呐幚泶笮】偸潜容^安全的。 大批處理可能導(dǎo)致內(nèi)存問題或?qū)е麻L時間運行的事務(wù),從而增加了撤消/重做事務(wù)日志的大小

測試時間

我們的域?qū)嶓w模型如下所示:

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

@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 ,我們需要設(shè)置以下Hibernate屬性:

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

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

針對商業(yè)數(shù)據(jù)庫運行第一個測試,結(jié)果如下:

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


提取大小越大,則提取整個結(jié)果集所需的往返行程越少。 如果返回的行包含許多列,則較大的提取大小將按比例要求較大的數(shù)據(jù)庫緩沖區(qū)。

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

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


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

結(jié)論

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

  • 代碼可在GitHub上獲得 。

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

jdbc select語句

總結(jié)

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

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。