如何使用休眠跟踪结果集大小?

时间:2013-10-22 20:50:23

标签: java sql hibernate jdbc orm

我正在尝试检测和优化Java / 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统计数据似乎都无法访问这些信息。

有什么建议吗?提前谢谢。

3 个答案:

答案 0 :(得分:2)

有一个名为log4jdbc的项目提供代理JDBC驱动程序,它可以记录SQL(添加了绑定参数)以及计时统计信息,连接打开和关闭事件,甚至是ResultSet调用。有几个forks,至少有一个(称为log4jdbc-remix)日志结果集作为表。

我认为使用jdbc.sqltiming记录器应足以指出问题所在,然后如果需要,可以使用其他选项深入了解。但它听起来有可能破解它以获得结果集计数。

答案 1 :(得分: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 :(得分:-1)

行数? “select count ...”(它不像执行两次。计数执行得更快) 列数?反射。使用Class.getDeclaredMethods();