【发布时间】:2013-10-22 20:50:22
【问题描述】:
我正在尝试检测和优化 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 统计信息似乎都无法访问此信息。
有什么建议吗?提前致谢。
【问题讨论】:
-
在执行此操作之前,您始终可以使用相同的查询,但使用 count(*) :)
-
是的,这会起作用,但代价是(可能)将每个查询的执行时间加倍,所以这绝对是一个不完美的解决方案 :)
-
can't query.list().size() 给出获取的记录数?
-
进行计数不会使执行时间加倍。它没有从您的数据库中获取任何实际数据,只是一个包含行数的数字结果。对于明智的查询,它不应该造成那么多开销。但这些可能不是我们在这里讨论的;-)
-
C.猴子 - 是的,不是的。例如,如果查询进行表扫描或创建临时表等,它将执行两次这些操作。当然,我同意通过网络传输的数据很少(*)。
标签: java sql hibernate jdbc orm