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