了解Oracle SQL Developer中执行解释计划的结果

时间:2009-05-13 21:11:06

标签: oracle oracle-sqldeveloper sql-execution-plan

我正在尝试优化查询,但不太了解从解释计划返回的一些信息。谁能告诉我OPTIONS和COST专栏的重要性?在OPTIONS列中,我只看到单词FULL。在COST专栏中,我可以推断出较低的成本意味着更快的查询。但是,成本价值究竟代表什么,可接受的阈值是什么?

5 个答案:

答案 0 :(得分:102)

EXPLAIN PLAN的输出是Oracle查询优化器的调试输出。 COST是基于成本的优化器(CBO)的最终输出,其目的是选择应该使用多个不同的可能计划中的哪一个来运行查询。 CBO计算每个计划的相对成本,然后选择成本最低的计划。

(注意:在某些情况下,CBO没有足够的时间来评估每个可能的计划;在这些情况下,它只选择迄今为止发现的最低成本的计划)

通常,慢查询的最大贡献者之一是为查询提供服务所读取的行数(更准确地说是块),因此成本将基于部分 on需要读取优化程序估计的行数。

例如,假设您有以下查询:

SELECT emp_id FROM employees WHERE months_of_service = 6;

months_of_service列上有一个NOT NULL约束,上面有一个普通索引。)

优化者可以在此选择两个基本计划:

  • 计划1:读取“employees”表中的所有行,为每个行检查谓词是否为真(months_of_service=6)。
  • 计划2:读取months_of_service=6的索引(这会产生一组ROWID),然后根据返回的ROWID访问该表。

让我们假设“employees”表有1,000,000(100万)行。让我们进一步想象,months_of_service的值介于1到12之间,并且由于某种原因分布相当均匀。

计划1 的成本(涉及全面扫描)将是读取employees表中所有行的成本,大约等于1,000,000;但由于Oracle通常能够使用多块读取来读取块,因此实际成本会降低(取决于数据库的设置方式) - 例如让我们假设多块读取计数为10 - 全扫描的计算成本为1,000,000 / 10;总成本= 100,000。

计划2 的成本(包括INDEX RANGE SCAN和ROWID的表查找)将是扫描索引的成本,以及通过ROWID访问表的成本。我不会深入研究索引范围扫描的成本,但让我们假设索引范围扫描的成本是每行1;我们希望在12个案例中找到一个匹配,因此索引扫描的成本是1,000,000 / 12 = 83,333;加上访问表的成本(假设每次访问读取1个块,我们不能在这里使用多块读取)= 83,333;总费用= 166,666。

如您所见,计划1(完全扫描)的成本低于计划2的成本(索引扫描+ rowid访问) - 这意味着CBO将选择完整扫描。

如果优化器在此做出的假设是正确的,那么事实上,计划1将比计划2更可取,效率更高 - 这反驳了FULL扫描“始终不好”的神话。

如果优化器目标是FIRST_ROWS(n)而不是ALL_ROWS,结果将会大不相同 - 在这种情况下,优化器会支持计划2,因为它通常会更快地返回前几行,但代价是效率较低整个查询。

答案 1 :(得分:7)

CBO构建决策树,估算每个查询可用的每个可能执行路径的成本。成本由实例上设置的CPU_cost或I / O_cost参数设置。 CBO会根据查询将使用的表和索引的现有统计信息来估算成本。您不应该仅根据成本调整查询。成本允许您了解优化程序正在执行的操作。没有成本,你可以弄清楚为什么优化器选择它做的计划。降低成本并不意味着更快的查询。在某些情况下,这是真的,并且会出现这种情况。成本取决于您的表统计数据,如果错误,则成本会出错。

调整查询时,您应该查看每个步骤的基数和行数。他们有道理吗?优化器假设的基数是否正确?行返回是否合理。如果存在的信息是错误的,那么优化器很可能没有正确决策所需的适当信息。这可能是由于表和索引以及cpu-stats的陈旧或缺失统计信息。在调优查询以最大限度地利用优化程序时,最好更新统计信息。在调优时,了解您的架构也非常有用。知道优化器何时选择了一个非常糟糕的决策,并用一个小提示将其指向正确的路径可以节省大量时间。

答案 2 :(得分:6)

以下是对Oracle使用EXPLAIN PLAN的参考:http://download.oracle.com/docs/cd/B19306_01/server.102/b14211/ex_plan.htm),其中包含有关此处列的详细信息:http://download.oracle.com/docs/cd/B19306_01/server.102/b14211/ex_plan.htm#i18300

您提到'FULL'表示查询正在进行全表扫描以查找您的数据。在某些情况下,这是可以的,否则就是索引/查询编写不良的指标。

通常,在解释计划中,您希望确保您的查询使用密钥,因此Oracle可以通过访问尽可能少的行来查找您正在查找的数据。最终,您有时只能使用表格的架构。如果成本仍然太高,您可能需要考虑调整架构的布局以使其更加基于性能。

答案 3 :(得分:3)

在最近的Oracle版本中,COST表示优化器期望查询采用的时间量,以单个块读取所需的时间量为单位表示。

因此,如果单个块读取花费2ms并且成本表示为“250”,则查询可能需要500ms才能完成。

优化器根据估计的单块和多块读取数以及计划的CPU消耗来计算成本。后者通过在其他操作之前执行某些操作来尝试避免高CPU成本操作来最小化成本非常有用。

这引发了一个问题,即优化者如何知道操作需要多长时间。最近的Oracle版本允许收集“系统统计信息”,这些信息绝对不能与表或索引的统计信息混淆。系统统计数据是硬件性能的度量,主要是:

  1. 单个块读取需要多长时间
  2. 多块读取需要多长时间
  3. 多块读取的大小(由于表格范围小于最大值以及其他原因,通常与最大值不同)。
  4. CPU性能
  5. 根据系统的运行环境,这些数字可能会有很大差异,可以存储不同的统计数据集用于“白天OLTP”操作和“夜间批量报告”操作,如果您愿意,可以存储“月末报告”

    根据这些统计信息集,可以在不同的操作环境中评估给定的查询执行计划的成本,这可能会促进在某些时候使用全表扫描或在其他时间进行索引扫描。

    成本并不完美,但优化者在每次发布时都会更好地进行自我监控,并且可以将实际成本与估算成本进行比较,以便为未来做出更好的决策。这也使得预测变得更加困难。

    请注意,成本不一定是挂钟时间,因为并行查询操作会占用多个线程的总时间。

    在旧版本的Oracle中,忽略了CPU操作的成本,并且根据init参数有效地修复了单块和多块读取的相对成本。

答案 4 :(得分:1)

FULL可能指的是全表扫描,这意味着没有使用索引。这通常表明出现了问题,除非查询应该使用表中的所有行。

成本是一个数字,表示不同负载,处理器,内存,磁盘,IO和高数字的总和通常是坏的。移动到计划的根目录时,这些数字会相加,并且应检查每个分支以找出瓶颈。

您可能还想查询v $ sql和v $ session以获取有关SQL语句的统计信息,这将包含所有类型的资源,计时和执行的详细指标。