MySQL的解释输出非常简单。PostgreSQL的是更复杂一点。我还没有能够找到一个很好的资源,解释了这一点。

你能描述一下究竟是什么解释是说或至少点我的方向的一个良好的资源?

有帮助吗?

解决方案

Explaining_EXPLAIN.pdf 也可以提供帮助。

其他提示

我总是发现混乱,是启动成本vs总成本。我谷歌这样每次我忘了它,这把我带回到这里,这无法解释的差异,这就是为什么我要写这个的答案。这是我收集的 Postgres EXPLAIN 文档, 解释,因为我理解它。

这里有一个例子是从一个应用程序,管理一个论坛:

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:

graphical explanation of first query

(当你使用PgAdmin,你可以点你的老鼠在一个组件来阅读费用的详细信息。)

成本被表示为一组,例如成本 LIMITcost=0.00..3.39 和费用的依次扫描 postcost=0.00..15629.12.第一数目在该组的 启动成本 第二个数字是 总费用.因为我用 EXPLAIN 而不 EXPLAIN ANALYZE, 这些费用估计数,而不是实际的措施。

  • 启动成本 是一个棘手的概念。它不只是代表量的时间之前,组件 开始.它代表的数量之间的时间分开始执行(阅读的数据)和当 对组输出其第一行.
  • 总费用 是的整个执行时间分,从它开始的时候读取数据时,它完成编写其输出。

作为一种并发症,每个"家长"的节点的费用包括成本的其孩子的节点。在该文本表示,树表示由压痕,例如 LIMIT 是父母和节点 Seq Scan 是它的孩子。在PgAdmin表示,箭头指从孩子父母的方向上流动的数据—这可能是违反直觉的,如果你熟悉的曲线理论。

该文件说,费用包括所有儿童节点,但是注意到总费用的父母 3.39 小得多的总成本是孩子 15629.12.总费用不包括因为一件喜欢的 LIMIT 不需要处理它的整个输入。看看 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)

和图形的方式:

graphical explanation of second query

再一次,在顺序上的扫描 post 没有启动费用:它开始输出行。但是,排序具有明显的启动成本 23283.24 因为它有 排序的整个表之前,它可以输出,即使一个单一行.总费用的排序 23859.27 只是稍高于启动成本,反映了一个事实,即一旦整个数据集已经进行排序,在排序的数据可以发现非常迅速。

注意到启动时间 LIMIT 23283.24 是完全相等的启动时间的排序。这是不是因为 LIMIT 本身具有较高的启动时间。它实际上具有零启动时间本身,但是 EXPLAIN 卷上所有的儿童成本为每个父母,所以 LIMIT 启动时间,包括总和的启动时间的儿童。

这一汇总的成本可以使它难以理解的执行费用的各个组成部分。例如,我们的 LIMIT 有零启动时间,但这不是显而易见的第一眼。由于这个原因,其他几个人联系 explain.depesz.com, 一个工具创建的,由休伯特*Lubaczewski(a。k.a.depesz),可以帮助理解 EXPLAIN 通过除其他外,减去了孩子的费用从父母的成本。他提到了一些其他的复杂性 短篇博客 关于他的工具。

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

这个想法是,每个步骤都有1个或2个数据集到达并由某个规则处理。如果只有一个数据集,则对该数据集执行该操作。 (例如,扫描索引以确定所需的行,过滤数据集或对其进行排序。)如果是两个,则两个数据集是进一步缩进的两个数据集,并且它们由您看到的规则连接。大多数规则的含义可以合理地容易猜到(特别是如果你之前已经阅读过一堆解释计划),但是你可以尝试通过查看文档来验证单个项目,或者(更简单)通过将短语投入到谷歌以及一些关键词,如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中找到它想要的行,然后使用快速排序对该数据集进行排序(如果数据不适合,使用的排序将会改变在RAM中,然后把它放在一边。

接下来,它扫描orditematt_attributeid_idx以从orderitemattribute中找到它想要的行,然后使用快速排序对该数据集进行排序。

然后获取两个数据集并合并它们。 (合并连接是一种<!>“zipping <!>”操作,它将并行处理两个已排序的数据集,在匹配时发出连接的行。)

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

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

也有一个,这里是相同的结果,这让我更清楚问题出在哪里是

PgAdmin 将向您显示解释计划的图形表示。在两者之间来回切换可以真正帮助您理解文本表示的含义。但是,如果您只是想知道它的用途,您可以随时使用GUI。

PostgreSQL的官方文档提供了有关如何理解解释输出的有趣,全面的解释

如果您安装了pgadmin,那么就会有一个Explain按钮,它会给出文本输出,绘制正在发生的事情的图表,显示过滤器,排序和子集合并,我觉得它们对于查看正在发生的事情非常有用。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top