如何使用 Oracle 正确执行 SELECT 查询的性能测试?

Posted

技术标签:

【中文标题】如何使用 Oracle 正确执行 SELECT 查询的性能测试?【英文标题】:How do I correctly performance test SELECT queries with Oracle? 【发布时间】:2011-04-18 23:19:31 【问题描述】:

我想测试两个查询以了解它们的性能,而不是只查看执行计划。我一直在 Tom Kyte 的网站上看到他这样做是为了收集有关他的理论的证据。

我相信性能测试有很多陷阱,例如,当我第一次在 SQL developer 中运行查询时,该查询可能会返回一些公平的数字。再次运行完全相同的查询,立即返回。服务器或客户端上必须有某种缓存,我知道这很重要 - 但是我只对非缓存性能感兴趣。

性能测试的指导方针是什么?以及如何编写重复查询的性能测试?我只是写一个匿名块和循环吗?如何获取时序信息、平均值、中位数、标准偏差?

【问题讨论】:

看看这个***.com/questions/2179512/… 对于所有响应者,作为开发人员,我感到绝望。我没有知识或工具。 :| 【参考方案1】:

Oracle(和其他数据库)缓存查询,您可以在其中看到您描述的行为。 “硬”解析意味着查询没有查询计划,这让 Oracle 根据索引和统计信息确定查询计划。 “软”解析是当您随后运行 相同查询 并收到即时结果时发生的情况,因为查询计划存在并且 Oracle 重复使用它。见the Ask Tom question about it for more details。

注意EXPLAIN output:

使用基于成本的优化器,执行计划可以并且确实会随着基础成本的变化而变化。 EXPLAIN PLAN 输出显示了在解释语句时 Oracle 如何运行 SQL 语句。由于执行环境和解释计划环境的不同,这可能与 SQL 语句实际执行期间的计划有所不同。

关注非缓存性能给出了最坏的情况,但考虑到缓存会发生 - 非缓存基准在日常使用中是不现实的。

【讨论】:

嗨,天哪,小马们,你的绝地是最强大的。我更新了我的问题。如何对查询进行计时并重复运行? @JavaRocky:查询的时间取决于实例上的资源(部分是由于负载)和网络流量(如果通过 Internet 或 WAN 则更多) - 这不是有效的基准。 TKPROF 可能更符合您的需求。 虽然您对执行计划的缓存是正确的,但这不太可能对整体执行时间产生很大影响,除非系统上存在非常显着的解析争用。更可能的是,实际运行执行计划所需的数据块缓存。【参考方案2】:

要构建 OMG Ponies 的答案,根据时间进行调整是可能的,但并不现实。在每种情况下,您都必须从完全缓存的缓冲区缓存开始,或者从完全空的缓冲区缓存开始,这些都不能代表现实——尤其是在没有竞争负载的情况下。

当我进行调优时,它通常针对有活动的实时系统,我专注于调整逻辑 I/O,或者通过使用扩展 SQL 跟踪 (dbms_monitor.session_trace_enable / dbms_monitor.session_trace_disable) 和 tkprof 实用程序,或者使用 SQL *Plus 和 set autotrace traceonly - 它完成了查询的所有工作,但丢弃了输出,因为我通常对观看数以百万计的行滚动不感兴趣。

确切的机制通常涉及绑定 SQL,使用如下:

 variable :my_bind1 number;
 variable :my_bind2 varchar2(30);

 begin
   :my_bind1 := 42;
   :my_bind2 := 'some meaningful string';
 end;
 /

 set timing on;
 set autotrace traceonly;

 [godawful query with binds]

 set autotrace off;

在结果中,我正在寻找我期望的计划,即排序的比较值(假设存在),最重要的是,一致 I/O 的数量。这就是 Oracle 必须以一致模式读取多少块才能满足查询。我找不到引用的原始出处,但我认为是 Method R 的 Cary Milsap。

“调整您的逻辑 I/O,然后您的物理 I/O 将随之而来。”

【讨论】:

【参考方案3】:

在性能调整中,如果您查看的唯一数据是挂钟时间,那么您将只能获得整个画面的一小部分。您至少需要查看执行计划以及 IO 统计信息,以便确定如何最好地调整查询。

此外,您需要消除导致性能问题的其他原因 - 例如如果在许多查询中存在一般性能问题,则可能不仅仅是其中一个问题的问题 - 它可能是架构问题、数据库上的大量并发活动,甚至是底层硬件问题。

我遇到过与您之前描述的类似的问题;例如某种类型的查询应该非常快,第一次运行需要 30 秒,然后会稳定到一两秒。然而,当我查看执行计划时,很明显它正在使用全表扫描,因为它无法使用已创建的唯一索引。第一次运行查询时,大部分数据被加载到缓存中(实际上,涉及到两级缓存——数据库缓冲区缓存,以及磁盘上的存储级缓存),因此后续的全表扫描速度非常快。

【讨论】:

【参考方案4】:

什么是正确的? 由于 11g 有一些额外的复杂性需要考虑。优化器 pre peeking 变得更加智能,并且 sql 计划稳定性有很大的影响。这两个特性使数据库自动调整,但也可能在性能测试期间产生意想不到的影响,例如因为并非所有计划的变体在测试开始时都是已知的并被接受。 这可能是第二次测试运行的原因,即第一次运行后的第二天,突然运行得更快,没有任何明显的变化。 由于 11g 性能测试与编写逻辑正确的代码相比不太重要。例如,笛卡尔积和过滤掉一个不同的值范在功能上是正确的,但在大多数情况下是错误的代码,因为它获取的数据比逻辑需要的多。 如果查询获取了真正需要的数据并且处于正确的控制结构中,则让数据库进程在维护窗口期间调整代码。在许多情况下,测试环境和生产环境之间的差异使得无法安全地进行比较。 不要误解我的意思,测试很重要,但与 11g 之前的性能测试相比,主要是为了逻辑,需要采取额外的步骤。 阅读精彩请看Oracle® Database 2 Day + Performance Tuning Guide 11g Release 2 (11.2)

【讨论】:

以上是关于如何使用 Oracle 正确执行 SELECT 查询的性能测试?的主要内容,如果未能解决你的问题,请参考以下文章

oracle查看历史session

oracle dg 。从机上 查询 select max(SEQUENCE#) from v$archived_log; 啥也查不到。主机上可以查到。

为啥mssql的OPENQUERY取oracle某表时只返回了一行数据,而在pl/sql中可以查到表中有两行数据,求解答?

如何杀死oracle死锁进程

ORACLE 中如何把A用户的增删改查权限赋给B用户

如何查看oracle数据库中的所有表