2013-10-22 30 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记录器应该足以指出问题出在哪里,那么如果需要的话,您可以使用其他选项进行深入研究。但听起来可以通过它来获得结果集计数。