查询第一次执行慢,但第二次/第三次执行快
Posted
技术标签:
【中文标题】查询第一次执行慢,但第二次/第三次执行快【英文标题】:Query Execute Slow First Time But Fast on Second/Third Time 【发布时间】:2020-03-04 13:58:09 【问题描述】:我们在 Oracle 查询中看到了一个非常奇怪的情况。下面的查询,
SELECT e.C1, MAX (e.Some)
FROM MyTable e
WHERE e.Code = :Code
GROUP BY E.C1
ORDER BY MAX (e.Some)
请注意,该表包含大约 500 万条记录,并且 Code 是主键。
第一次尝试时,它会在 60/70 秒内返回值,但之后,它会在 500 毫秒内返回结果。
Oracle 中是否有任何参数嗅探,或者我们可以在 Oracle 中使用 OPTION(RECOMPILE) 吗?
【问题讨论】:
结果缓存已关闭? docs.oracle.com/database/121/TGDBA/… Google:Oracle 中的 RESULT_CACHE。 使用相同的 :Code 值?尝试查看统计数据,看看它在做什么。我怀疑第一次执行是从磁盘读取索引和表的块,所以它很慢(尽管 70 秒对于 5M 行来说太慢了,除非你有一个非常慢的磁盘子系统),下次它们在内存,所以没有 I/O。或者可能是 result_cache,正如其他人所建议的那样。 Oracle 中存在参数嗅探,称为自适应游标共享 (ACS)。 【参考方案1】:Oracle 查询在第二次或第三次执行时可能会加快有几个原因:
-
缓冲区缓存 - Oracle 会将经常使用的表和索引块放入内存中。检查这一点的最简单方法是在启用
set autotrace on
后多次在SQL*Plus 中运行查询。如果“物理读取”的值在第一次运行后消失,那么缓存会导致差异。但缓存也可以发生在存储或操作系统级别。
解析/执行构建缓慢 - 在极少数情况下,Oracle 可能需要很长时间才能构建初始执行计划。如果使用动态采样,则尤其如此,Oracle 将读取表的一部分以弥补不良的优化器统计信息。查找此问题的一种方法是查找与您的查询同时运行的其他系统查询。造成这种情况的另一个常见原因是系统或固定对象统计信息不正确,这意味着 Oracle 可能很难构建查询来检查权限等内容。
基数反馈 (11g)/统计反馈 (12c+) - 通过比较预期基数和实际基数,优化器能够从错误中学习。相同的 SQL_ID 在 GV$SQL 中是否有不同的 PLAN_HASH_VALUE?如果是这样,则执行计划会随着时间而改变。
结果缓存 - Oracle 服务器和客户端可以存储查询的结果。这种类型的缓存实际上比人们想象的要少得多,因为实际上缓冲区缓存更有用 - 当您可以存储可以服务多个查询的数据块时,为什么要将单个特定结果存储在内存中?
【讨论】:
谢谢。我们也将数据复制到 SQL Server。相同数量的数据和相同的查询在第一次尝试时会在 1 秒内返回数据,不知道为什么 Oracle 在第一次尝试时总是很慢。 @user960567 数据是否也复制到了 Oracle?这些问题的一个常见原因是糟糕的优化器统计信息,这可能在加载表时发生。如果在有 0 行时收集表统计信息,然后将 500 万行加载到表中,则优化器将很难使用该信息构建良好的执行计划。即使您配置了默认统计任务,当数据发生显着变化时手动收集统计数据也很重要。 (但这是一个猜测 - 如果您添加更多信息,我可以更好地猜测根本原因。) Oracle 是该表的主源。同一个表被复制到 SQL Server。每天大约有数千行插入/更新。在用于缓解不良计划的 SQL Server 中,我们使用OPTION(RECOMPILE)
。不幸的是,我在 Oracle 中没有看到类似的东西。无论如何,谢谢,乔恩。【参考方案2】:
它可能没有使用主键的索引。尝试解释计划检查。尝试使用规则库来强制使用索引:
select /*+ RULE */ from ...
另外,请 DBA 运行表分析以更新统计信息。
【讨论】:
以上是关于查询第一次执行慢,但第二次/第三次执行快的主要内容,如果未能解决你的问题,请参考以下文章
为什么Sql Server的查询有时候第一次执行很慢,第二次,第三次执行就变快了
在QT中用 QSqlQuery query;查询, 第一次 query.exec();结果是对的,可是第二次执行的时候读的数据是错的