您如何解释查询的解释计划?


88

尝试了解SQL语句的执行方式时,有时建议查看解释计划。在解释(理解)解释计划时应该经历什么过程?什么应该脱颖而出,“哦,这很出色?” 与“哦,不,那是不对的”。

Answers:


80

每当我看到评论说完整表扫描不好并且索引访问很好时,我都会感到不寒而栗。全表扫描,索引范围扫描,快速全索引扫描,嵌套循环,合并联接,哈希联接等只是分析人员必须理解的访问机制,并且结合了数据库结构知识和查询目的。为了得出任何有意义的结论。

完全扫描只是读取数据段(表或表(子)分区)的大部分块的最有效方法,尽管它通常可以指示性能问题,但这仅在上下文中它是否是实现查询目标的有效机制。作为数据仓库和BI专家,我对性能的第一警告是基于索引的访问方法和嵌套循环。

因此,对于如何阅读解释计划的机制,Oracle文档是一个很好的指南:http : //download.oracle.com/docs/cd/B28359_01/server.111/b28274/ex_plan.htm#PFGRF009

也请仔细阅读《性能调优指南》。

还有一个Google用于“基数反馈”,该技术可使用解释计划将查询中各个阶段的基数估计与执行过程中遇到的实际基数进行比较。我相信Wolfgang Breitling是该方法的作者。

因此,底线是:了解访问机制。了解数据库。了解查询的意图。避免经验法则。


5
我知道前9个字之后就是您。就像“曲调的名字” ...我可以用少于或等于n个单词识别Dave A帖子...

我会对您使用“大”感到有些困惑...有时数据可能无法很好地聚集在索引列周围,以至于FTS甚至无法对10%的行执行索引扫描...

1
在10%上-绝对如此。如果每个块有200行,并且要查找0.5%的行,那么从理论上讲,您可能必须访问100%的块才能获得所有值,因此,它甚至比10%还要极端。
David Aldridge


5

以下两个示例显示了使用INDEX进行的完全扫描和快速扫描。

最好专注于您的费用和基数。查看示例,使用索引可以降低运行查询的成本。

这有点复杂(而且我没有100%的处理能力),但是从根本上讲Cost是CPU和IO成本的函数,而Cardinality是Oracle希望解析的行数。减少这两者都是一件好事。

不要忘记查询的成本会受到查询和Oracle优化器模型(例如COST,CHOOSE等)以及运行统计信息的频率的影响。

范例1:

扫描http://docs.google.com/a/shanghainetwork.org/File?id=dd8xj6nh_7fj3cr8dx_b

示例2使用索引:

索引http://docs.google.com/a/fukuoka-now.com/File?id=dd8xj6nh_9fhsqvxcp_b

并且正如已经建议的那样,请注意TABLE SCAN。您通常可以避免这些情况。


嗯,规则模式没有成本...所以我想您的陈述以某种绝对的方式是正确的,但我会说这根本上是不准确的。如果您说选择,则可以获取RBO或CBO。CBO是唯一计算成本的方法。

4

寻找诸如顺序扫描之类的东西可能会有所帮助,但实际情况在于数字中……除非数字只是估计值!什么是通常远远高于在寻找一个查询更多有用的计划是看实际的执行。在Postgres中,这是EXPLAIN和EXPLAIN ANALYZE之间的区别。EXPLAIN ANALYZE实际上执行查询,并获取每个节点的实际计时信息。这样一来,您可以查看实际发生的情况,而不是计划者的想法会发生的情况。很多时候,您会发现顺序扫描根本不是问题,而是查询中的其他问题。

另一个关键是确定实际的昂贵步骤是什么。许多图形工具将使用大小不同的箭头来指示计划的不同部分成本。在这种情况下,只需查找有细箭头进入而粗箭头离开的步骤。如果您不使用GUI,则需要关注这些数字并寻找它们突然变大的地方。稍加练习,就可以很容易地找出问题所在。


3

实际上,对于此类问题,最好的方法是ASKTOM。特别是他对这个问题的答案包含在线Oracle文档的链接,其中解释了许多此类规则。

要记住的一件事是,解释计划实际上是最好的猜测。

学习使用sqlplus并尝​​试使用AUTOTRACE命令将是一个好主意。有了一些困难的数字,您通常可以做出更好的决策。

但是您应该询问。他对此一无所知:)


2

说明的输出告诉您每个步骤花费了多长时间。首先是要找到花费很长时间的步骤并了解它们的含义。诸如顺序扫描之类的事情告诉您,您需要更好的索引-这主要是对特定数据库和经验的研究。


2

一个“哦,不,那是不对的”通常以表格扫描的形式出现。表扫描不使用任何特殊索引,可以有助于清除内存高速缓存中的所有有用索引。例如,在postgreSQL中,您会发现它看起来像这样。

Seq Scan on my_table  (cost=0.00..15558.92 rows=620092 width=78)

有时,表扫描比使用索引查询行更理想。但是,这是您似乎正在寻找的那些危险信号模式之一。


2
(完整)表扫描不一定会清除内存缓存。
a_horse_with_no_name 2012年

2

基本上,您应该看一下每个操作,并根据给定的操作原理知道这些操作是否“有意义”。

例如,如果要联接两个表,A和B分别位于它们的列C和D(AC = BD),并且您的计划在表上显示聚集索引扫描(SQL Server术语-不确定oracle术语) A,然后嵌套循环连接到表B上的一系列聚簇索引查找,您可能会认为存在问题。在这种情况下,您可能希望引擎先执行一对索引扫描(对联接列上的索引进行扫描),然后再进行合并联接。进一步的调查可能会发现不良的统计信息,从而使优化器选择该连接模式或实际上不存在的索引。


1

查看在计划的每个子部分中花费的时间百分比,并考虑引擎在做什么。例如,如果要扫描表,请考虑在要扫描的字段上放置索引


1

我主要寻找索引或表扫描。这通常告诉我,我在where语句或join语句中的重要列上缺少索引。

http://www.sql-server-performance.com/tips/query_execution_plan_analysis_p1.aspx

如果在执行计划中看到以下任何内容,则应考虑它们为警告信号并调查它们是否存在潜在的性能问题。从性能的角度来看,它们每个都不理想。

* Index or table scans: May indicate a need for better or  additional indexes.
* Bookmark Lookups: Consider changing the current clustered index,
  consider using a covering index, limit
  the number of columns in the SELECT
  statement.
* Filter: Remove any functions in the WHERE clause, don't include wiews
  in your Transact-SQL code, may need
  additional indexes.
* Sort: Does the data really need to be sorted? Can an index be used to
  avoid sorting? Can sorting be done at
  the client more efficiently? 

并非总是可以避免这些情况,但是您可以避免的越多,查询性能就会越快。


1
表扫描并非全都不好-根据表返回/处理的记录数,全表扫描可能比索引扫描更快(如果无论如何要还原记录,都将进行索引扫描并从表格中完整读取-2个步骤,而不是1个步骤。
ScottCher

-7

经验法则

(您可能还想阅读详细信息:

几个大表的表扫描

使用唯一索引
索引包括所有必填字段

最常见的胜利

在我所看到的大约90%的性能问题中,最简单的方法就是将具有很多(4个或更多)表的查询分解为2个较小的查询和一个临时表。


2
表格扫描通常被视为坏事,而这最初是没有经验的人们所关注的。这在很大程度上取决于从该表返回的记录数,当它更快地执行全表扫描而不是索引查找时,会有一个阈值。
ScottCher

8
令人沮丧的建议。临时表和拆分查询无法解决90%的性能问题。您生活在哪个世界?
TheSoftwareJedi's

@Jedi,我生活的世界中,索引几乎是正确的,并且数据库的结构非常合理。不过,我很想阅读您的答案。
AJ。
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.