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

时间:2008-09-17 02:26:19

标签: sql database performance oracle sql-execution-plan

当试图理解SQL语句的执行方式时,有时建议您查看解释计划。在解释(理解)解释计划时应该经历的过程是什么?应该突出的是,“哦,这真的很棒吗?”与“哦不,那不对。”

11 个答案:

答案 0 :(得分:78)

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

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

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

还要仔细阅读“性能调优指南”。

还有一个谷歌用于“基数反馈”,这是一种技术,其中解释计划可用于将查询中各个阶段的基数估计与执行期间经历的实际基数进行比较。我相信Wolfgang Breitling是这种方法的作者。

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

答案 1 :(得分:13)

这个问题太大了,无法在这样的问题中回答。您应该花一些时间阅读Oracle's Performance Tuning Guide

答案 2 :(得分:5)

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

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

它有点复杂(我没有100%处理它)但基本上Cost是CPU和IO成本的函数,而基数是Oracle期望解析的行数。减少这两者是一件好事。

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

示例1:

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

示例2使用索引:

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

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

答案 3 :(得分:4)

寻找连续扫描之类的东西可能有点用处,但实际情况是数字...除非数字只是估计值!通常比查看计划更有用的是查看实际的执行。在Postgres中,这是EXPLAIN和EXPLAIN ANALYZE之间的区别。 EXPLAIN ANALYZE实际执行查询,并获取每个节点的实时定时信息。这可以让你看到实际正在发生什么,而不是规划者认为会发生什么。很多时候你会发现顺序扫描根本不是问题,而是查询中的其他内容。

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

答案 4 :(得分:3)

真正针对这些问题,最好的办法是ASKTOM。特别是他对这个问题的回答包含了在线Oracle文档的链接,其中解释了很多这类规则。

要记住的一点是,解释计划确实是最好的猜测。

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

但你应该ASKTOM。他知道一切:)

答案 5 :(得分:2)

解释的输出告诉你每个步骤花了多长时间。首先要找到花费很长时间并了解其含义的步骤。像顺序扫描这样的事情告诉你需要更好的索引 - 这主要是研究你的特定数据库和经验。

答案 6 :(得分:2)

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

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

有时,表扫描比使用索引查询行更理想。但是,这是您似乎正在寻找的那些红旗图案之一。

答案 7 :(得分:2)

基本上,你看看每个操作,看看操作是否“有意义”,因为你知道它应该如何工作。

例如,如果您在各自的列C和D(AC = BD)上连接两个表A和B,并且您的计划显示聚簇索引扫描(SQL Server术语 - 不确定oracle术语)在表A上,然后嵌套循环连接到表B上的一系列聚簇索引,您可能认为存在问题。在这种情况下,您可能希望引擎执行一对索引扫描(通过连接列上的索引),然后进行合并连接。进一步调查可能会显示错误的统计信息,使优化器选择连接模式,或者实际上不存在的索引。

答案 8 :(得分:1)

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

答案 9 :(得分: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? 
     

并不总是可以避免   这些,但你可以避免的越多   他们,查询性能更快   将是。

答案 10 :(得分:-6)

经验法则

(你可能也想了解细节:

几个大表的表扫描

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

最常见的胜利

在我看到的大约90%的性能问题中,最简单的胜利是将包含大量(4个或更多)表的查询分解为2个较小的查询和一个临时表。