什么是PostgreSQL解释完全告诉我?

MySQL的解释输出非常简单。 PostgreSQL的更复杂一点。 我还没有find一个可以解释它的好资源。

你能描述一下究竟是在说什么,或者至less指向一个好资源的方向吗?

Explaining_EXPLAIN.pdf也可以帮助。

它从大部分缩进执行到最小缩进,我相信从计划的底部到顶部。 (因此,如果有两个缩进的部分,则首先执行页面下方的那个部分,然后当他们遇到另一个执行时,执行join它们的规则。)

这个想法是,每一步都有1或2个数据集到达并按某个规则进行处理。 如果只有一个数据集,则对该数据集进行该操作。 (例如扫描一个索引来找出你想要的行,过滤一个数据集,或者对它进行sorting。)如果两个数据集是两个进一步缩进的数据集,并且它们按照你所看到的规则连接起来。 大部分规则的含义可以被合理地容易地猜到(特别是如果你之前已经阅读了一堆解释计划),但是你可以尝试通过查看文档来validation单个项目,或者通过简单地将该短语放入Google以及像EXPLAIN这样的几个关键字。

这显然不是一个完整的解释,但它提供了足够的背景,通常你可以找出你想要的。 例如,从一个实际的数据库中考虑这个计划:

 explain analyze select a.attributeid, a.attributevalue, b.productid from orderitemattribute a, orderitem b where a.orderid = b.orderid and a.attributeid = 'display-album' and b.productid = 'ModernBook'; ------------------------------------------------------------------------------------------------------------------------------------------------------------ Merge Join (cost=125379.14..125775.12 rows=3311 width=29) (actual time=841.478..841.478 rows=0 loops=1) Merge Cond: (a.orderid = b.orderid) -> Sort (cost=109737.32..109881.89 rows=57828 width=23) (actual time=736.163..774.475 rows=16815 loops=1) Sort Key: a.orderid Sort Method: quicksort Memory: 1695kB -> Bitmap Heap Scan on orderitemattribute a (cost=1286.88..105163.27 rows=57828 width=23) (actual time=41.536..612.731 rows=16815 loops=1) Recheck Cond: ((attributeid)::text = 'display-album'::text) -> Bitmap Index Scan on (cost=0.00..1272.43 rows=57828 width=0) (actual time=25.033..25.033 rows=16815 loops=1) Index Cond: ((attributeid)::text = 'display-album'::text) -> Sort (cost=15641.81..15678.73 rows=14769 width=14) (actual time=14.471..16.898 rows=1109 loops=1) Sort Key: b.orderid Sort Method: quicksort Memory: 76kB -> Bitmap Heap Scan on orderitem b (cost=310.96..14619.03 rows=14769 width=14) (actual time=1.865..8.480 rows=1114 loops=1) Recheck Cond: ((productid)::text = 'ModernBook'::text) -> Bitmap Index Scan on id_orderitem_productid (cost=0.00..307.27 rows=14769 width=0) (actual time=1.431..1.431 rows=1114 loops=1) Index Cond: ((productid)::text = 'ModernBook'::text) Total runtime: 842.134 ms (17 rows) 

尝试阅读它自己,看看是否有道理。

我读到的是,数据库首先扫描id_orderitem_productid索引,使用它来查找orderitem的行,然后使用快速sorting对该数据集进行sorting(如果数据不适合RAM,则所使用的sorting将改变),然后设置在旁边。

接下来,它扫描orditematt_attributeid_idx以查找来自orderitemattribute所需行,然后使用快速sorting对该数据集进行sorting。

然后把这两个数据集合并起来。 (合并连接是一种“压缩”操作,在这种操作中,它并行地处理两个已sorting的数据集,并在匹配时发出连接的行)。

正如我所说,你通过计划内部部分到外部,从下到上。

我总是觉得困惑的部分是启动成本与总成本。 我每次忘了Google,都会把它带回到这里,这并不能解释这种差异,这就是为什么我要写这个答案。 这是我从Postgres的EXPLAIN文档中收集到的, 据我了解。

以下是pipe理论坛的应用程序示例:

 EXPLAIN SELECT * FROM post LIMIT 50; Limit (cost=0.00..3.39 rows=50 width=422) -> Seq Scan on post (cost=0.00..15629.12 rows=230412 width=422) 

这是来自PgAdmin的graphics解释:

第一个查询的图形化解释

(当您使用PgAdmin时,您可以将鼠标指向组件以读取成本详细信息。)

成本被表示为一个元组,例如LIMITcost=0.00..3.39cost=0.00..3.39 ,顺序扫描postcost=0.00..15629.12cost=0.00..15629.12 。 元组中的第一个数字是启动成本 ,第二个数字是总成本 。 因为我使用了EXPLAIN而不是EXPLAIN ANALYZE ,所以这些成本是估算的,而不是实际的量度。

  • 启动成本是一个棘手的概念。 它不仅仅表示组件启动之前的时间量。 它表示组件开始执行(读取数据)和组件输出其第一行之间的时间量。
  • 总成本是组件的整个执行时间,从数据开始读取到写入输出结束。

作为一种复杂情况,每个“父”节点的成本包括其子节点的成本。 在文本表示中,树由缩进表示,例如, LIMIT是父节点, Seq Scan是其子节点。 在PgAdmin表示中,箭头指的是从孩子到父母 – 数据stream的方向 – 如果熟悉图论,这可能是违反直觉的。

文档中说成本包含了所有的子节点,但是注意父节点3.39的总成本要比子15629.12的总成本要小得多。 总成本不包括在内,因为像LIMIT这样的组件不需要处理整个input。 参见EXPLAIN SELECT * FROM tenk1 WHERE unique1 < 100 AND unique2 > 9000 LIMIT 2; 例如在Postgres的EXPLAIN文档中 。

在上面的例子中,两个组件的启动时间为零,因为在开始写入行之前,组件都不需要做任何处理:顺序扫描读取表的第一行并发出。 LIMIT读取第一行然后发出。

什么时候组件需要做大量的处理才能开始输出任何行? 有很多可能的原因,但让我们看一个清晰的例子。 这里是从前,但现在包含一个ORDER BY子句相同的查询:

 EXPLAIN SELECT * FROM post ORDER BY body LIMIT 50; Limit (cost=23283.24..23283.37 rows=50 width=422) -> Sort (cost=23283.24..23859.27 rows=230412 width=422) Sort Key: body -> Seq Scan on post (cost=0.00..15629.12 rows=230412 width=422) 

并以graphics方式:

第二个查询的图形化解释

再一次,在post顺序扫描没有启动成本:它立即开始输出行。 但这种sorting有一个很大的启动成本23283.24因为它必须sorting整个表之前,它甚至可以输出一个单一的行 。 sorting23859.27的总成本只比启动成本略高,反映了一旦整个数据集被sorting后,sorting后的数据就可以很快地发出。

请注意, LIMIT 23283.24的启动时间与sorting的启动时间完全相同。 这不是因为LIMIT本身启动时间很长。 它本身实际上没有启动时间,但是EXPLAIN汇总每个父代的所有子代价值,所以LIMIT启动时间包括其子代的启动时间总和。

成本的上涨可能使得难以理解每个单独组件的执行成本。 例如,我们的LIMIT启动时间为零,但乍一看并不明显。 出于这个原因,其他几个人链接到由Hubert Lubaczewski(又名depesz)创build的explain.depesz.com工具,该工具有助于理解EXPLAIN ,其中包括从父母成本中扣除儿童费用。 他在一篇关于他的工具的短篇博文中提到了一些其他的复杂性。

还有一个在线帮助工具Depesz ,它将突出分析结果的昂贵部分。

也有一个,这里的结果是一样的 ,这对我来说是更清楚的问题。

PgAdmin将向您显示解释计划的graphics表示。 在两者之间来回切换确实可以帮助您理解文本表示的含义。 但是,如果你只是想知道它是怎么回事,你可能只能总是使用GUI。

PostgreSQL的官方文档提供了一个有趣的,彻底的解释如何理解解释的输出。

如果你安装了pgadmin,那么就有一个Explainbutton,同时给出文本输出,绘制正在发生的事情的图表,显示filter,sorting和子集合并,我发现真正有用的是看看发生了什么。