繁体   English   中英

如何清除 oracle 执行计划缓存以进行基准测试?

[英]How do I clear oracle execution plan cache for benchmarking?

在 oracle 10gr2 上,我有几个正在比较性能的 sql 查询。 但是在他们第一次运行之后,v$sql 表存储了用于缓存的执行计划,所以对于其中一个查询,我从第一次运行的 28 秒到 5 秒后的 go。

我试过了

ALTER SYSTEM FLUSH BUFFER_CACHE;

运行此命令后,查询始终以 5 秒的速度运行,我认为这是不准确的。

想也许从缓存中删除订单项本身:

delete from v$sql where sql_text like 'select * from....

但我收到有关无法从视图中删除的错误。

彼得回答了你提出的问题。

alter system flush shared_pool;

这是您将用于“从缓存中删除准备好的语句”的语句。

(准备好的语句不是从共享池中刷新的唯一对象,该语句的作用不止于此。)

正如我在之前的评论中(关于你的问题)所指出的, v$sql不是一个表。 它是一个动态性能视图,是 Oracle 内部内存结构的一种方便的类似表格的表示形式。 您对动态性能视图只有 SELECT 权限,不能从中删除行。


刷新共享池和缓冲区缓存?

以下内容没有直接回答您的问题。 相反,它回答了一个根本不同(也许更重要)的问题:

我们通常应该刷新共享池和/或缓冲区缓存来衡量查询的性能吗?

简而言之,答案是否定的。

我认为 Tom Kyte 很好地解决了这个问题:

http://www.oracle.com/technology/oramag/oracle/03-jul/o43asktom.html
http://www.oracle.com/technetwork/issue-archive/o43asktom-094944.html

<摘录>

实际上,调优工具不这样做很重要。 运行测试,忽略结果,然后运行两到三次并平均这些结果是很重要的。 在现实世界中,缓冲区缓存永远不会没有结果。 绝不。 调整时,您的目标是减少逻辑 I/O (LIO),因为这样物理 I/O (PIO) 就会自行处理。

考虑一下:刷新共享池和缓冲区缓存比不刷新它们更人为。 我怀疑,大多数人似乎对此持怀疑态度,因为它与传统智慧背道而驰。 我将向您展示如何执行此操作,但不是这样您就可以将其用于测试。 相反,我将用它来证明为什么它是徒劳且完全人为的(因此会导致错误的假设)。 我刚刚启动了我的电脑,我已经对一个大表运行了这个查询。 我“刷新”缓冲区缓存并再次运行它:

</摘录>

我认为 Tom Kyte 是完全正确的。 在解决性能问题方面,我认为“清除 oracle 执行计划缓存”通常不是可靠基准测试的一个步骤。

让我们解决对性能的担忧。

您告诉我们,您已经观察到,与后续执行(约 5 秒)相比,查询的第一次执行时间(约 28 秒)要长得多,即使在刷新(所有索引和数据块)缓冲区缓存时也是如此。

对我来说,这表明硬解析正在做一些繁重的工作。 这要么是很多工作,要么是遇到了很多等待。 这可以被调查和调整。

我想知道统计信息是否不存在,并且优化器在准备查询计划之前花费了大量时间收集统计信息。 这是我要检查的第一件事,即收集所有引用表、索引和索引列的统计信息。

如果您的查询连接了大量表,则 CBO 可能正在考虑对连接顺序进行大量排列。

对 Oracle 跟踪的讨论超出了本答案的范围,但这是下一步。

我想您可能想要跟踪事件 10053 和 10046。

这是 Tom Kyte 的“事件 10053”讨论的链接,您可能会觉得有用:

http://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:63445044804318


切线相关的轶事故事:硬解析性能

几年前,我确实看到一个查询在第一次执行时以 MINUTES 为单位,随后以秒为单位执行。 我们发现第一次执行的大部分时间都花在了硬解析上。

这个问题查询是由一个 CrystalReports 开发人员编写的,他无辜地(天真地?)加入了两个庞大的报告视图。

其中一个视图是 62 个表的连接,另一个视图是 42 个表的连接。

该查询使用了基于成本的优化器。 跟踪显示,这不是等待时间,而是所有 CPU 时间用于评估可能的连接路径。

每个供应商提供的“报告”视图本身并不算太糟糕,但是当其中两个加入时,速度慢得令人痛苦。 我相信问题在于优化器正在考虑的大量连接排列。 有一个实例参数限制优化器考虑的排列数量,但我们的修复是重新编写查询。 改进后的查询只加入了查询实际需要的十几个表。

(最初的即时短期“创可贴”修复是在报告生成任务运行之前安排在早上早些时候运行查询。这使得报告生成“更快”,因为报告生成运行利用了已经在共享池中准备语句,避免硬解析。

创可贴修复不是真正的解决方案,它只是将问题转移到查询的初步执行中,而没有注意到执行时间长。

我们的下一步可能是为查询实现“存储大纲”,以获得稳定的查询计划。

当然,语句重用(避免硬解析,使用绑定变量)是 Oracle 中的规范模式。 它提高了性能、可扩展性、yada、yada、yada。

这个轶事可能与您观察到的问题完全不同。


HTH

自从我使用 Oracle 以来已经有一段时间了,但我相信执行计划缓存在共享池中。 试试这个:

alter system flush shared_pool;

缓冲区缓存是 Oracle 存储最近使用的数据以最小化磁盘 io 的地方。

我们最近在性能调优查询方面做了大量工作,导致查询性能不一致的一个罪魁祸首是 Oracle 所在的文件系统缓存。

有可能在您刷新 Oracle 缓存时,文件系统仍然拥有您的查询所要求的数据,这意味着该查询仍将快速返回。

不幸的是,我不知道如何清除文件系统缓存 - 我只是使用了我们非常有用的系统管理员提供的非常有用的脚本。

从 gv$sqlarea where sql_id ='7hu3x8buhhn18' 中查找 SQL_ID select address,hash_value,inst_id,users_executing,sql_text 的地址和哈希值;

从共享池中清除计划 exec sys.dbms_shared_pool.purge('0000002E052A6990,4110962728','c');

验证select address,hash_value,inst_id,users_executing,sql_text from gv$sqlarea where sql_id ='7hu3x8buhhn18';

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM