EXPLAIN
EXPLAIN
显示一个语句的查询计划
概要
EXPLAIN [ANALYZE] [VERBOSE] statement
描述
EXPLAIN 显示Greenplum计划器为提供的语句所生成的查询计划。查询计划是一颗节点计划树。在计划中的每个节点代表了一个操作,例如表扫描、连接、聚集或者是一个排序操作。
因为每个节点直接向它上面的节点提供行结果,所以计划应该从下往上进行阅读。最底层的节点通常是一些表扫描操作(顺序扫描、索引扫描或者是位图扫描)。如果查询要求连接、聚集或者排序(或者其他在原始行上的操作),那么需要再扫描节点增加这些操作的节点。计划最顶层的节点通常是Greenplum的motion节点(重分布、显式重分布、广播或者聚集motion)。这些操作符代表了在查询处理期间在分片示例之间移动行数据。
EXPLAIN 的输出是树中每个节点有一行,显示基本的节点类型,紧接着是由计划器为执行该计划节点时的代价评估:
- cost — 通过用取磁盘页面的次数来度量。即,1.0代表一个连续磁盘页面的读取。首先是启动代价(获取第一行的代价),第二个代价是总的代价(获取所有行的代价)。注意总的代价假设所有的行都将要被取回,但并不是总是这种情况(比如使用LIMIT语句)。
- rows — 该计划节点总的输出行数。这通常是小于实际由计划节点处理或者扫描的行数,主要是由于任何一个WHERE条件语句的评估选择性。理想情况下,最高层的节点估计近似等于实际由该查询返回、更新或者删除的行数。
- width — 该计划节点所有行输出的总的字节数。
值得注意的是更上一层的节点的代价包括了所有它孩子节点的代价。计划中最顶层节点是估计执行整个计划的代价。该数字是计划器寻求最小化的地方。同时也需要意识到代价仅仅反应了查询优化器关心的部分。特别是,代价没有考虑将结果行传输到客户端所花费的时间。
EXPLAIN ANALYZE 导致该语句被实际执行,而不仅仅是被计划。EXPLAIN ANALYZE 计划显示实际的结果以及计划器的评估。这个对于看是否计划器评估接近实际的情况非常有用。除了显示在EXPLAIN计划中的信息,EXPLAIN ANALYZE还要外加显示下面的信息:
- 总的花费在执行该查询的时间间隔(以毫秒为单位)。
- 在一个计划节点操作中涉及到的workers(Segment)的数量。只有返回行的Segment被计入。
- 一个操作中输出最多行的Segment返回的最大行数。如果多个Segment输出了相同数量的行数,取time to end最长的那个Segment。
- 在一个操作中输出最多行的Segment的ID。
- 对于相关的操作,该操作使用的work_mem。如果work_mem不足以在内存中执行操作,计划将显示有多少数据溢出到磁盘上以及对于使用工作内存最少的执行Segment要求了多少趟对数据的处理。例如:
Work_mem used: 64K bytes avg, 64K bytes max (seg0). Work_mem wanted: 90K bytes avg, 90K bytes max (seg0) to abate workfile I/O affecting 2 workers. [seg0] pass 0: 488 groups made from 488 rows; 263 rows written to workfile [seg0] pass 1: 263 groups made from 263 rows
- 产生最多行的Segment检索到第一行所花的时间(以毫秒计),以及在该Segment上获取所有行所花费的时间。如果<time> to first row同<time> to end相等,则前者有可能被省略。
BEGIN; EXPLAIN ANALYZE ...; ROLLBACK;
参数
- name
- 将要执行的预备语句的名称。
- parameter
- 预备语句的实际参数值。这一定是一个产生与该参数数据类型兼容的值的表达式,参数的数据类型则是在预备语句被创建时定义的。
注解
为了允许查询计划器在优化查询时能做出合理的知情决策,ANALYZE语句需要被执行用来记录关于在表内数据的分布统计信息。如果用户还没有完成这个操作(或者如果表内数据从上一次执行ANALYZE语句后的统计分布发生了很大的变化),那么评估代价不会很符合实际的查询属性,同时因此会导致选择一个较差的计划被选中。
一个SQL语句在一个EXPLAIN ANALYZE命令被执行时执行会从Greenplum资源队列中排出。对于更多关于查询概括的信息,见Greenplum数据库管理员指南中的“查询画像”部分。更多关于资源队列的信息见Greenplum数据库管理员指南中的“用资源队列进行工作负载管理”部分。
示例
为了展示如何阅读一个EXPLAIN查询计划,考虑下面的一个简单查询的例子:
EXPLAIN SELECT * FROM names WHERE name = 'Joelle'; QUERY PLAN ------------------------------------------------------------ Gather Motion 2:1 (slice1) (cost=0.00..20.88 rows=1 width=13) -> Seq Scan on 'names' (cost=0.00..20.88 rows=1 width=13) Filter: name::text ~~ 'Joelle'::text
如果我们从下往上阅读该计划,查询优化器开始于顺序扫描表names。注意WHERE子句作为一个过滤条件被应用。这意味着一个扫描操作要检验扫描中的每一行是否满足该条件,同时返回那些满足条件的行。
扫描操作的结果将向上传递到一个gather motion操作。在Greenplum数据库中,gather motion是Segment向上传递行到Master的时机。在该例子中,我们有2个Segment实例发送到1个Master实例(2:1)。该操作工作在并行查询执行计划的slice1上。在Greenplum数据库中,一个查询计划被分成切片,这样每个查询计划的多个部分能够被Segment并行地执行。
该计划的估计启动代价是00.00(没有代价)以及总代价为20.88次取磁盘页。计划器认为该查询将会返回一行。
兼容性
在SQL标准中没有定义EXPLAIN语句。