了解 OracleSQLDeveloper 中执行解释计划的结果

我试图优化一个查询,但是不太理解从 解释计划返回的一些信息。有人能告诉我期权和成本列的重要性吗?在 OPTION 列中,我只看到单词 FULL。在 COST 列中,我可以推断出较低的成本意味着更快的查询。但是成本价值到底代表了什么,什么是可接受的阈值?

149916 次浏览

下面是在 Oracle: http://download.oracle.com/docs/cd/B19306_01/server.102/b14211/ex_plan.htm中使用 EXPLAIN PLAN 的参考资料,其中包含有关这里找到的列的特定信息: http://download.oracle.com/docs/cd/B19306_01/server.102/b14211/ex_plan.htm#i18300

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

通常,使用解释计划时,您希望确保查询使用了键,这样 Oracle 就可以通过访问尽可能少的行来找到您要查找的数据。最终,您对表的体系结构的了解有时也只能到此为止。如果成本仍然太高,您可能需要考虑调整模式的布局,使其更加基于性能。

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

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

您可能还希望查询 v $SQL 和 v $session 以获取关于 SQL 语句的统计信息,这将包含各种资源、计时和执行的详细指标。

CBO 构建一个决策树,估计每个查询可用的每个可能执行路径的成本。成本由实例上设置的 CPU _ Cost 或 I/O _ Cost 参数设置。CBO 对成本进行估算,尽可能利用查询将使用的表和索引的现有统计信息。您不应该仅仅基于成本来优化查询。成本使您能够理解为什么优化器正在做它所做的事情。无需成本,您就可以找出优化器为什么选择它所执行的计划。更低的成本并不意味着更快的查询。在某些情况下,这是正确的,而在某些情况下,这是错误的。成本是基于你的表统计数据,如果他们是错误的,成本将是错误的。

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

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

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

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

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

SELECT emp_id FROM employees WHERE months_of_service = 6;

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

优化者可能会在这里选择两种基本方案:

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

让我们想象一下“員”表有1,000,000(1百万)行。让我们进一步假设,month _ of _ service 的值范围从1到12,出于某种原因,它们的分布相当均匀。

第一计划的成本,包括一个全扫描,将是读取所有行的成本,员工表,这大约等于1,000,000; 但是,因为甲骨文通常能够读取块使用多块读取,实际成本将更低(取决于您的数据库是如何设置)-例如,让我们想象多块读取计数是10-计算的成本全扫描将是1,000,000/10; 总成本 = 100,000。

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

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

如果优化者在这里做出的假设是正确的,那么事实上,计划1将比计划2更可取,也更有效率——这驳斥了全面扫描“总是坏的”的神话。

如果优化器的目标是 FIRST _ ROWS (n)而不是 ALL _ ROWS,结果会大不相同——在这种情况下,优化器会倾向于 Plan 2,因为它通常会更快地返回前几行,代价是整个查询的效率较低。

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

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

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

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

  1. 一个块读需要多长时间
  2. 多块读取需要多长时间
  3. 多块读取的大小(通常不同于最大值,这是因为表的区域小于最大值,以及其他原因)。
  4. CPU 性能

根据系统的操作环境,这些数字可以有很大的不同,可以为“日间 OLTP”操作和“夜间批量报告”操作存储不同的统计数据集,如果愿意,还可以为“月底报告”存储不同的统计数据集。

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

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

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

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