2013-10-22 28 views
11

我試圖檢測和優化Java/Hibernate應用程序內的低效連接。我注意到,在某些情況下,由於結果集中連接的處理方式,導線數據流的效率非常低。如何使用hibernate跟蹤結果集大小?

讓我舉個例子。假設你有一個HQL查詢,看起來像這樣:

select s from Store s 
left join fetch s.items i 
left join fetch s.employees e 
left join fetch s.customers c 
where s.id = :id 

(忽略了片刻,這是不是一個聰明的查詢 - 它只是一個簡單的例子)。

如果您想象某商店有1000件商品,10名員工和100位客戶,那麼您將得到一個帶有1111個實體的java對象樹。這可能讓你想到從數據庫返回大約1111行,而實際上結果集有1,000,000行!

所有列的存在使情況變得更糟。如果你想象每個表格有5列,你可能會想象你回來了大約5555個「項目」,而結果集中的單元格數(行*列)實際上是20,000,000。

顯然,應用程序開發人員有責任瞭解此問題,而不是以這種方式編寫查詢。但是,這有時會發生無意(以不太嚴重的方式),並且能夠以某種方式識別這些情況來對應用程序進行測試將是非常好的。

但是,我一直無法找到任何計算方法(從Java/Hibernate應用程序中)計算原始結果集中的行數或列數。 Hibernate攔截器,Hibernate事件或Hibernate統計信息都不能訪問這些信息。

有什麼建議嗎?提前致謝。

+2

以及你可以總是使用相同的查詢,但計數(*)之前執行此:) – Apostolos

+0

是的,這將工作,代價(可能)的每個查詢的執行時間加倍,所以它肯定是不完美的解決方案:) –

+0

can not query.list()。size()給出記錄的取數? –

回答

-1

行數? 「select count ...」(它不像執行兩次,count執行得更快) column count?反射。用Class.getDeclaredMethods();

0

Hibernate是一個非常複雜的框架。正如您所看到的,與原始JDBC相比,它消耗了大量的總體執行時間。而且你的查詢並不需要創建1111對象,因爲當然,Hibernate使用緩存,二級緩存和其他黑暗技術來代理對象並保存一些內存,具體取決於配置。但是,如果您正在尋找任何方法來計算Java代碼中的某些統計信息,那麼您應該使用Hibernate Statistics,它們在某些情況下非常有用,確定它們不適合您?

QueryStatistics queryStats = stats.getQueryStatistics("from Store s"); 
queryStats.getCacheHitCount(); 
queryStats.getCacheMissCount(); 
queryStats.getCachePutCount(); 
queryStats.getExecutionCount(); 
queryStats.getExecutionAvgTime(); 
queryStats.getExecutionMaxTime(); 
queryStats.getExecutionMinTime(); 
queryStats.getExecutionRowCount(); 

SecondLevelCacheStatistics cacheStats = stats.getSecondLevelCacheStatistics("Sale.cache"); 
cacheStats.getElementCountInMemory(); 
cacheStats.getElementCountOnDisk(); 
cacheStats.getEntries(); 
cacheStats.getHitCount(); 
cacheStats.getMissCount(); 
cacheStats.getPutCount(); 
cacheStats.getSizeInMemory(); 

CollectionStatistics collectionStats = stats.getCollectionStatistics("Sale.items"); 
collectionStats.getFetchCount(); 
collectionStats.getLoadCount(); 
collectionStats.getRecreateCount(); 
collectionStats.getRemoveCount(); 
collectionStats.getUpdateCount(); 

而且有更多的選擇,探索http://www.javalobby.org/java/forums/t19807.html

2

有一個名爲log4jdbc項目,提供代理JDBC驅動程序,它可以記錄SQL(添加綁定參數)以及定時統計數據,連接打開並關閉事件,甚至是ResultSet調用。有幾個叉子,至少有一個(稱爲log4jdbc-remix)將結果集記錄爲表格。

我認爲使用jdbc.sqltiming記錄器應該足以指出問題出在哪裏,那麼如果需要的話,您可以使用其他選項進行深入研究。但聽起來可以通過它來獲得結果集計數。