休眠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 对这两个查询使用了不同的索引。

你能创建一个包含columnAcolumnL 的索引吗?

如果您有一个仅包含 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问题的主要内容,如果未能解决你的问题,请参考以下文章

oracle 10g 在查询结果列中添加rownum列,查询出的条数增多。

ORACLE 中ROWNUM

ORACLE 中ROWNUM用法总结!

Oracle的rownum原理和使用

Oracle 中的 ROWNUM 有替代品吗?

oracle中使用rownum获取数据