PostgreSQL解释到底告诉了我什么?

PostgreSQL解释到底告诉了我什么?,postgresql,Postgresql,MySQL的解释输出非常简单。PostgreSQL的有点复杂。我也没有找到一个好的资源来解释它 你能描述一下explain到底在说什么,或者至少告诉我一个好资源的方向吗?它从最缩进到最缩进,我相信从计划的底部到顶部。(因此,如果有两个缩进部分,则首先执行页面下方较远的一个部分,然后当它们相遇时执行另一个部分,然后执行连接它们的规则。) 其思想是,在每个步骤中,都有1到2个数据集到达,并按照某种规则进行处理。如果只有一个数据集,则对该数据集执行该操作。(例如,扫描索引以找出所需的行、筛选数据集或对

MySQL的解释输出非常简单。PostgreSQL的有点复杂。我也没有找到一个好的资源来解释它


你能描述一下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\u orderitem\u productid
索引,使用该索引从
orderitem
中找到它想要的行,然后使用快速排序对该数据集进行排序(如果数据不适合RAM,则使用的排序将改变),然后将其放在一边

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

然后,它获取这两个数据集并合并它们。(合并联接是一种“压缩”操作,它并行遍历两个已排序的数据集,当它们匹配时发出联接行。)


正如我所说的,从内部到外部,从下到上,您都可以完成该计划。

也会有所帮助。

将向您展示该计划的图形表示。在两者之间来回切换可以真正帮助您理解文本表示的含义。但是,如果您只想知道它将要做什么,您可以始终使用GUI。

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


还有一个,这里是,这让我更清楚问题出在哪里。

如果你安装了pgadmin,有一个解释按钮,在给出文本输出的同时,还绘制了发生了什么的图表,显示了我发现非常有用的过滤器、排序和子集合并,以查看发生了什么。

提供了一个有趣的,关于如何理解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的图形说明:

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

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

  • 启动成本是一个棘手的概念。它不仅仅表示组件启动之前的时间量。它表示从组件开始执行(读取数据)到组件输出其第一行的时间量
  • 总成本是组件的整个执行时间,从开始读取数据到完成写入输出
复杂的是,每个“父”节点的成本包括其子节点的成本。在文本表示中,树由缩进表示,例如,
LIMIT
是父节点,
Seq Scan
是其子节点。在PgAdmin表示法中,箭头从子级指向父级——数据流的方向——如果您熟悉图论,这可能会违反直觉

文档中说成本包括所有子节点,但请注意父节点
3.39
的总成本远小于其子节点
15629.12
的总成本。总成本不包括在内,因为像
LIMIT
这样的组件不需要处理其全部输入。请参阅
解释选择*FROM tenk1,其中unique1<100和unique2>9000限制2中的示例

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

组件何时需要进行大量处理才能开始输出任何行?有很多可能的原因,但让我们看一个明确的例子。这是以前的相同查询,但现在包含一个
orderby
子句:

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)
从图形上看:

再次在
post上进行顺序扫描<