oracle 评估SQL查询性能时要比较哪些指标?

oewdyzsn  于 2023-05-28  发布在  Oracle
关注(0)|答案(3)|浏览(218)

我最近观看了一个关于Oracle SQL性能调优的在线课程。在视频中,讲师在比较两个查询的性能时,不断比较Autotrace的COST值。
但我也从其他论坛和网站上读到,COST是特定于该查询的相对值,不应用于评估性能的绝对度量。他们建议考虑一致的获取、物理读取等。
因此,我的解释是,比较用于不同目的的完全不同的查询的COST值是没有意义的,因为COST值是相对的。但是当比较相同的两个查询时,其中一个查询为了“更好的性能”而稍微修改了一下,比较COST值是可以的。我的解释准确吗?
什么时候可以将COST值与其他指标进行比较?
在评估/比较查询性能时,我们应该查看哪些其他指标?

7xllpg7q

7xllpg7q1#

一般来说,我对比较两个查询之间的cost非常谨慎,除非您有非常具体的理由相信这是有意义的。
通常,人们不会查看优化器为之生成(接近)最优计划的99.9%的查询。人们会查看优化器生成了明显次优计划的查询。优化器会产生一个次优的计划,原因有两个--要么是它不能将查询转换成它可以优化的形式(在这种情况下,人类可能需要重写查询),要么是它用来进行估计的统计数据不正确,所以它认为是最优的计划不是。(当然,还有其他原因可能导致查询速度变慢--例如,可能优化器生成了一个最佳计划,但该最佳计划正在执行表扫描,因为缺少索引。)
如果我看到一个查询速度很慢,而且这个查询看起来写得相当好,并且有一组合理的索引可用,那么统计数据最有可能是问题的根源。然而,由于cost完全基于统计数据,这意味着优化器的cost估计是不正确的。如果它们不正确,cost不正确的高或不正确的低的可能性大致相等。如果我查看一个查询的查询计划,我知道它需要聚合数十万行来生成一个报告,并且我看到优化器为它分配了一个个位数的cost,我知道在这条线沿着某个地方,它估计一个步骤将返回太少的行。为了调优该查询,我需要提高cost,以便优化器的估计准确地反映实际情况。如果我查看一个查询的查询计划,我知道应该只需要扫描少数几行,而我看到成千上万的cost,我知道优化器估计某个步骤将返回太多的行。为了调优该查询,我将需要向下调整cost,以便优化器的估计反映实际情况。
如果使用gather_plan_statistics hint,您将在查询计划中看到估计的行数和实际的行数。如果优化器的估计接近实际情况,则计划可能相当不错,cost可能相当准确。如果优化器的估计不正确,那么计划可能很差,cost可能是错误的。尝试使用cost指标来调优查询,而不首先确认cost是否合理地接近实际情况,很少有效率。
就我个人而言,我会忽略cost,而专注于那些随着时间的推移可能会保持稳定并且实际上与性能相关的指标。我倾向于关注逻辑读取,因为大多数系统都是I/O绑定的,但也可以使用CPU时间或运行时间(不过,运行时间往往不是特别稳定,因为它取决于运行查询时缓存中的内容)。如果你在看一个计划,重点放在估计与。实际行计数不在cost上。

yx2lnoni

yx2lnoni2#

查询的 * 实际运行时间 * 是调优查询的最重要指标。我们可以在99.9%的时间里忽略成本和其他指标。
如果查询相对较小且速度较快,我们可以很容易地重新运行它并使用GATHER_PLAN_STATISTICS提示找到实际运行时间:

-- Add a hint to the query and re-run it.
select /*+ gather_plan_statistics */ count(*) from all_objects;

-- Find the SQL_ID of your query.
select sql_id, sql_fulltext
from gv$sql
where lower(sql_text) like '%gather_plan_statistics%'
    and sql_text not like '%quine%';

-- Plus in the SQL_ID to find an execution plan with actual numbers.
select * from table(dbms_xplan.display_cursor(sql_id => 'bbqup7krbyf61', format => 'ALLSTATS LAST'));

如果查询非常慢,并且我们不能轻松地重新运行它,则生成SQL监视器报告。这些数据通常在最后一次执行后的几个小时内可用。

-- Generate a SQL Monitor report.
select dbms_sqltune.report_sql_monitor(sql_id => 'bbqup7krbyf61') from dual;

有很多关于解释结果的书。最基本的是,你要首先检查执行计划,并专注于具有最大“A时间”的操作。如果您想了解查询或优化器在哪里出错,请将“E-Rows”与“A-Rows”进行比较,因为估计的基数驱动大多数优化器决策。
示例输出:

SQL_ID  bbqup7krbyf61, child number 0
-------------------------------------
select /*+ gather_plan_statistics */ count(*) from all_objects
 
Plan hash value: 3058112905
 
--------------------------------------------------------------------------------------------------------------------------------------------------------------
| Id  | Operation                                 | Name               | Starts | E-Rows | A-Rows |   A-Time   | Buffers | Reads  |  OMem |  1Mem | Used-Mem |
--------------------------------------------------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                          |                    |      1 |        |      1 |00:00:03.58 |     121K|    622 |       |       |          |
|   1 |  SORT AGGREGATE                           |                    |      1 |      1 |      1 |00:00:03.58 |     121K|    622 |       |       |          |
|*  2 |   FILTER                                  |                    |      1 |        |  79451 |00:00:02.10 |     121K|    622 |       |       |          |
|*  3 |    HASH JOIN                              |                    |      1 |  85666 |  85668 |00:00:00.12 |    1479 |      2 |  2402K|  2402K| 1639K (0)|
|   4 |     INDEX FULL SCAN                       | I_USER2            |      1 |    148 |    148 |00:00:00.01 |       1 |      0 |       |       |          |
...
smdnsysy

smdnsysy3#

与工程中的大多数事情一样,它实际上归结为为什么/你要比较和评估什么。
COST是Oracle基于时间的一般估计,用作其内部优化器中的排名度量。This answer explains that selection process pretty well
一般来说,COST作为度量是比较两个不同查询的预期计算时间的好方法,因为它测量了表示为块读取数的查询的估计时间成本。因此,如果您正在比较同一查询的性能,一个针对时间进行优化的查询,那么COST是一个很好的度量标准。
但是,如果您的查询或系统是瓶颈或时间以外的约束(例如,存储器效率),则COST将是针对其进行优化的较差度量。在这些情况下,你应该选择一个与你的最终目标相关的指标。

相关问题