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

当试图理解SQL语句如何执行时,有时build议查看解释计划。 在解释解释计划(有意义)时应该经历什么过程? 什么应该突出,“哦,这是出色的工作?” 对“哦,不,这是不对的。”

每当我看到整个表格都不好,索引访问不错的时候,我就会不寒而栗。 全表扫描,索引范围扫描,快速全索引扫描,嵌套循环,合并连接,散列连接等都是访问机制,必须由分析人员理解,并结合对数据库结构和查询目的的了解以达成任何有意义的结论。

全面扫描仅仅是读取数据段(表或表(子)分区)的大部分块的最有效方式,并且它通常可以指示性能问题,但这只是在上下文是否是实现查询目标的有效机制。 作为一个数据仓库和商务智能家伙,我的头号警告标志是一个基于索引的访问方法和嵌套循环。

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

请仔细阅读“性能调整指南”。

也有一个谷歌的“基数反馈”,其中一个解释计划可以用来比较查询的各个阶段的基数的估计与执行过程中经历的实际基数的技术。 我相信沃尔夫冈·布雷特林是这个方法的作者。

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

这个话题太大了,不能回答这样的问题。 您应该花些时间阅读Oracle的“性能调优指南”

以下两个示例显示了使用INDEX的FULL扫描和FAST扫描。

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

这有点复杂(我没有100%的处理),但基本上,成本是CPU和IO成本的函数,基数是Oracle预计要parsing的行数。 减less这两个是件好事。

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

例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

如已经build议的,小心桌面扫描。 你通常可以避免这些。

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

另一个关键是确定实际昂贵的步骤是什么。 许多graphics工具将使用不同大小的箭头来表示计划的多less不同部分的成本。 在这种情况下,只要find有细箭头进来的步骤,并留下一个粗箭头。 如果你不使用graphics用户界面,你需要仔细观察这些数字,并寻找它们突然变大的地方。 稍加练习就可以很容易地找出问题所在。

对于像这样的问题,最好的办法就是ASKTOM 。 特别是他对这个问题的回答包含了在线Oracle文档的链接,在那里解释了很多这样的规则。

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

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

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

解释的输出告诉你每一步已经走了多久。 首先要找出需要花费很长时间的步骤,理解它们的含义。 顺序扫描等事情告诉你,你需要更好的索引 – 这主要是研究你的特定数据库和经验的问题。

一个“哦,不,这是不正确的”通常是一个表扫描的forms。 表扫描不使用任何特殊的索引,可以有助于清除每一个有用的内存caching。 例如在PostgreSQL中,你会发现它看起来像这样。

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

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

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

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

看看在计划的每个小节花费的时间百分比,并考虑发动机在做什么。 例如,如果正在扫描一个表格,请考虑在正在扫描的字段上放置一个索引

我主要查找索引或表扫描。 这通常告诉我,我错过了where语句或join语句中重要列的索引。

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

如果您在执行计划中看到以下任何内容,则应该考虑警告标志并调查潜在的性能问题。 从性能的angular度来看,他们每个人都不太理想。

 * 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? 

避免这种情况并不总是可能的,但是越能避免这些情况,查询性能就越快。

经验法则

(你可能也想读一下细节:

  • Oracle Docs
  • ASKTOM
  • SQL Server文档

几张大桌子的桌面扫描

使用独特的索引
索引包括所有必填字段

最常见的胜利

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