73

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

4

5 回答 5

122

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

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

一般来说,导致查询缓慢的最大因素之一是为查询服务而读取的行数(更准确地说是块),因此成本将部分取决于优化器估计需要的行数被阅读。

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

SELECT emp_id FROM employees WHERE months_of_service = 6;

(该months_of_service列上有一个 NOT NULL 约束和一个普通索引。)

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

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

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

计划 1的成本,它涉及一次 FULL SCAN,将是读取 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,因为它通常会更快地返回前几行,但代价是整个查询的效率较低.

于 2009-05-15T07:20:47.037 回答
7

CBO 构建决策树,估计每个查询可用的每个可能执行路径的成本。成本由实例上设置的 CPU_cost 或 I/O_cost 参数设置。CBO 会根据查询将使用的表和索引的现有统计信息尽可能地估计成本。您不应仅根据成本调整查询。成本可以让您了解优化器为什么要这样做。无需成本,您就可以弄清楚为什么优化器选择了它所做的计划。更低的成本并不意味着更快的查询。在某些情况下这是正确的,并且在某些情况下是错误的。成本基于您的餐桌统计数据,如果它们错误,则成本将是错误的。

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

于 2009-05-14T17:41:14.137 回答
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 可以通过访问尽可能少的行数来找到您要查找的数据。最终,您有时只能在表的体系结构方面做到这一点。如果成本仍然太高,您可能不得不考虑调整架构的布局以更加基于性能。

于 2009-05-13T21:25:43.103 回答
3

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

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

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

这就提出了优化器如何知道操作需要多长时间的问题。最近的 Oracle 版本允许收集“系统统计信息”,绝对不要将其与表或索引的统计信息相混淆。系统统计数据是对硬件性能的测量,最重要的是:

  1. 单块读取需要多长时间
  2. 多块读取需要多长时间
  3. 多块读取有多大(由于表范围小于最大值以及其他原因,通常与可能的最大值不同)。
  4. 中央处理器性能

这些数字可以根据系统的运行环境而有很大差异,并且可以为“白天 OLTP”操作和“夜间批量报告”操作以及“月末报告”存储不同的统计数据集(如果您愿意)。

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

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

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

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

于 2013-09-02T09:42:49.237 回答
1

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

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

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

于 2009-05-13T21:26:35.943 回答