首次执行时休眠查询速度缓慢

4
我有一个(非常)复杂的应用程序,它将GET请求翻译成多个Hibernate查询到Oracle数据库中。它基本上检索散布在约100个表中的对象属性。我必须在极限情况下(即大结果集)实现最大请求时间。在边缘情况下,性能在第一次调用时非常慢(即经过一段时间后)。之后,即使我刷新缓冲区和共享池,查询也会快得多。这适用于相同的GET请求,即请求相同的对象。请求另一个对象,但再次请求相同的属性需要很长时间才能完成第一次调用。例如,相同的查询、相同的条件,总行数在(低)千位数:第一次调用:26,000毫秒;在清除缓冲区/共享池后的第一次调用:2800毫秒;清除后的第二次调用:1200毫秒。从网络上的研究中,我已经发现刷新池不一定真正地刷新它,所以我不能依赖它。作为一个警告,我是一名开发人员,对Oracle有很好的工作知识,但不是DBA,并且没有完整的DBA访问权限。 我怀疑以下原因导致第一次执行缓慢: 1. Oracle进行了艰难的解析,需要很长时间(执行的查询可能包含多达数千个参数):我无法找出“坏”硬解析需要多长时间。企业管理器告诉我,在多次执行我的查询时,他只进行了1次硬解析,因此似乎不太可能。 2. 查询本身需要很长时间,但被缓存,并且我的操作没有清空缓存(可能是磁盘缓存?):同样,企业管理器不同意,并显示总体上非常低的查询时间。 3. 我一开始怀疑Hibernate/Java原因(毕竟有很多要创建的对象),但在性能巨大差异的情况下,这似乎不太可能。 我不知道如何进行性能调整,正在寻找有用的阅读材料和/或关于为什么第一次执行如此缓慢的不同想法。

1
为了排除硬解析时间,您可能需要跟踪查询 - 输出将向您显示解析花费的时间。有一些罕见情况下,解析可能需要几秒钟,例如具有数百个UNION ALL或数十个公共表达式的查询。 - Jon Heller
1
你可能也想看一下这样的解释计划:select * from table(dbms_xplan.display_cursor(sql_id => 'YOUR SQL_ID HERE'));。Oracle有一些功能只在第一次执行后才会启动,例如自适应游标共享,自适应计划和基数反馈。请特别注意输出中的“Notes”部分。还要在GV$SQL中检查是否存在相同查询的多个行,不同的计划或任何其他看起来“奇怪”的东西。 - Jon Heller
1个回答

0

在Oracle DB中,第一次查询通常比任何后续查询花费更多时间。

在这种情况下,仅依赖于Oracle缓存似乎不是一个好的做法。但是,如果您可以通过执行虚拟查询(例如,在应用程序启动后立即执行)来模仿首次查询,则可能会派上用场。它可以帮助减少任何后续相同调用的执行时间。

尽管这种解决方案可能有助于提高性能,但更可靠的方法是在应用程序级别引入编程缓存。它可以用于重复获取的实体或任何其他非持久对象。

请注意,如果问题的范围仅限于数据库,则可以在Database Administrators Stack Exchange上提出问题。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接