Postgres 计划中的“结果”节点和“附加”节点中实际发生了什么?

seb*_*seb 4 postgresql explain postgresql-9.6

我有一个表(postgres 9.6),它按日期划分为大约 70 个子表。

EXPLAIN下面的输出被截断,因为它的大部分是每个子表的相同位图索引/堆扫描(这里是完整的详细输出)。我感兴趣的部分是树顶部附近的AppendResult节点。

  1. 从我能够收集到的(例如这里和其他地方),Append只是所有子查询的总和。事实上,它需要比这长约 3.5 秒。多余的从哪里来?
  2. I can only find the one reference to Resultwhich states当您的查询选择某个常量值时,将使用此操作。此节点大约需要 7 秒,但查询未选择常量值。

如果可能的话,我很想节省这 10 秒,但我实际上并不知道这些节点在做什么,所以我不知道该尝试什么。

EXPLAIN ANALYZE 输出:

  ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
  ?                                                                                      QUERY PLAN                                                                                       ?
  ?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
  ? HashAggregate  (cost=4459946.40..4473566.96 rows=1089645 width=64) (actual time=26289.308..26419.989 rows=190112 loops=1)                                                             ?
  ?   Group Key: frontend_prescription.processing_date, frontend_prescription.pct_id, substr((frontend_prescription.presentation_code)::text, 1, 9)                                       ?
  ?   Buffers: shared hit=172527                                                                                                                                                          ?
  ?   ->  Result  (cost=0.00..4296499.68 rows=10896448 width=60) (actual time=29.021..18762.432 rows=10769038 loops=1)                                                                    ?
  ?         Buffers: shared hit=172527                                                                                                                                                    ?
  ?         ->  Append  (cost=0.00..4160294.08 rows=10896448 width=44) (actual time=29.011..11454.952 rows=10769038 loops=1)                                                              ?
  ?               Buffers: shared hit=172527                                                                                                                                              ?
  ?               ->  Seq Scan on frontend_prescription  (cost=0.00..0.00 rows=1 width=88) (actual time=0.010..0.010 rows=0 loops=1)                                                      ?
  ?                     Filter: ((presentation_code)::text ~~ '0212%'::text)                                                                                                              ?
  ?               ->  Bitmap Heap Scan on frontend_prescription_201110  (cost=607.38..39094.77 rows=127148 width=44) (actual time=28.998..126.694 rows=183185 loops=1)                    ?
  ?                     Filter: ((presentation_code)::text ~~ '0212%'::text)                                                                                                              ?
  ?                     Heap Blocks: exact=2083                                                                                                                                           ?
  ?                     Buffers: shared hit=2788                                                                                                                                          ?
  ?                     ->  Bitmap Index Scan on idx_frontend_prescription_201110_presentation  (cost=0.00..575.59 rows=37356 width=0) (actual time=28.576..28.576 rows=183185 loops=1)   ?
  ?                           Index Cond: (((presentation_code)::text ~>=~ '0212'::text) AND ((presentation_code)::text ~<~ '0213'::text))                                                ?
  ?                           Buffers: shared hit=705
  <snip>    
Run Code Online (Sandbox Code Playgroud)

查询:

EXPLAIN (ANALYZE,BUFFERS) SELECT
  processing_date,
  pct_id,
  SUBSTR(presentation_code, 1, 9) AS chemical_id,
  SUM(total_items) AS items,
  SUM(actual_cost) AS cost,
  SUM(quantity) AS quantity
FROM
  frontend_prescription
WHERE presentation_code LIKE '0212%'
GROUP BY
  processing_date,
  pct_id,
  chemical_id
Run Code Online (Sandbox Code Playgroud)

jja*_*nes 6

Append 必须做一些缓冲区管理。它还对一些时钟函数(gettimeofday例如)进行了大量调用,以满足 EXPLAIN ANALYZE 的计时组件。该开销可能是主要的时间槽。

在您的情况下,结果节点正在计算 SUBSTR 函数的结果。您可以在详细计划的输出字段中看到这一点。它还对某些时钟函数进行了大量调用。

如果你运行explain (analyze, timing off),它的执行时间应该告诉你在你的 EXPLAIN ANALYZE 中有多少时间用于检测开销。