休眠oracle rownum问题
Posted
技术标签:
【中文标题】休眠oracle rownum问题【英文标题】:hibernate oracle rownum issue 【发布时间】:2012-09-09 18:54:19 【问题描述】:SELECT * FROM (
select *
from tableA
where ColumnA = 'randomText'
ORDER BY columnL ASC
) WHERE ROWNUM <= 25
在执行此查询时,由于一些 Oracle 优化,该查询大约需要 14 分钟才能执行。如果我删除 where 子句,查询会在几秒钟内执行。表的大多数列都有索引,包括上面提到的那些。当我使用休眠时,我对查询的结构没有太大的灵活性。
这个查询也立即返回结果,结果正确:
SELECT *
FROM (
select *
from tableA,
dual
where ColumnA = 'randomText'
ORDER BY columnL ASC
) WHERE ROWNUM <= 25
有什么我可以做的,使用休眠?
更新:我使用 EntityManager.createQuery(),也使用 setMaxResults(25) 和 setFirstResult()。上面的查询是hibernate查询的样子,观察日志
【问题讨论】:
能否请您发布 HQL 本身?您的原始查询是否包含集合连接?映射本身也很有用。 你能提供这两个查询的解释计划吗? @ctapobep pastebin.com/qjzu5HKc 是 HQL 。如您所见,没有连接。 @JensSchauder 用于没有连接和 where 子句的查询,解释计划:static.inky.ws/image/2857/image.jpg 用于在 DUAL 上连接的查询,解释计划:static.inky.ws/image/2858/image.jpg 用于没有连接但 where 子句的查询,解释计划: static.inky.ws/image/2859/image.jpg 最后一个是no join and no where 子句,对不起。 【参考方案1】:我没有得到与您的查询完全匹配的解释计划,但似乎 oracle 对这两个查询使用了不同的索引。
你能创建一个包含columnA
和columnL
的索引吗?
如果您有一个仅包含 columnA
的索引,您可以删除它而不会对其他查询的性能产生很大影响。
另一种方法是添加提示以使用更快查询中使用的索引。但这需要您使用本机 sql。
【讨论】:
查询是动态构建的,因此 columnL 可能是表的任何列。因此复合索引不是一个可行的解决方案。【参考方案2】:这意味着您正在使用hibernate/jpa?如果是这样,我猜您正在使用EntityManager.createNativeQuery()
创建查询?尝试删除您的 where-restriction 并改用 Query
上的 .setMaxResults(25)
。
无论如何,为什么需要外部选择?不会
select *
from tableA
where ColumnA = 'randomText'
AND ROWNUM <= 25
ORDER BY columnL ASC
产生预期的结果?
【讨论】:
没有外部选择 rownum 不遵守顺序 然后尝试在没有外部选择和 setMaxResults 的情况下使用它。如果这不起作用,我会感到非常惊讶。 @Korgen 我使用 EntityManager.createQuery(),也使用 setMaxResults(25) 和 setFirstResult()。上面的查询是hibernate查询的样子,观察日志。 @user1677819 这是一些有价值的信息,应该进入你的问题;-\ @Korgen 我没有将 Rownum 放在 where 子句中的灵活性,因为将实际查询放在子查询中是 hibernate 所做的。以上是关于休眠oracle rownum问题的主要内容,如果未能解决你的问题,请参考以下文章