Postgres查询计划器调整

时间:2018-09-03 09:54:52

标签: sql postgresql query-planner

我们有一个包含测量数据的数据库(9.6)。相关查询为3个表:

  • aufnehmer(即传感器),5e + 2项,
  • zeitpunkt(即时间点),4e + 6个条目
  • wert(即值),6e + 8个条目

aufnehmer:zeitpunkt = m:n,以wert作为映射表。所有相关列均已建立索引。

以下查询

select count(*) from wert w
inner join aufnehmer a on w.aufnehmer_id = a.id
inner join zeitpunkt z on z.id = w.zeitpunkt_id
where a.id = 12749 
and z.zeitpunkt <= ('2018-05-07')::timestamp without time zone
and z.zeitpunkt >= ('2018-05-01')::timestamp without time zone;

生成此查询计划: enter image description here

Aggregate  (cost=3429124.66..3429124.67 rows=1 width=8) (actual time=66.252..66.252 rows=1 loops=1)
  ->  Nested Loop  (cost=571.52..3429084.29 rows=16149 width=0) (actual time=19.051..65.406 rows=15942 loops=1)
        ->  Index Only Scan using idx_aufnehmer_id on aufnehmer a  (cost=0.28..8.29 rows=1 width=4) (actual time=0.007..0.008 rows=1 loops=1)
              Index Cond: (id = 12749)
              Heap Fetches: 1
        ->  Nested Loop  (cost=571.24..3428914.50 rows=16149 width=4) (actual time=19.040..64.502 rows=15942 loops=1)
              ->  Bitmap Heap Scan on zeitpunkt z  (cost=570.67..22710.60 rows=26755 width=4) (actual time=1.551..3.407 rows=24566 loops=1)
                    Recheck Cond: ((zeitpunkt <= '2018-05-07 00:00:00'::timestamp without time zone) AND (zeitpunkt >= '2018-05-01 00:00:00'::timestamp without time zone))
                    Heap Blocks: exact=135
                    ->  Bitmap Index Scan on idx_zeitpunkt_zeitpunkt_order_desc  (cost=0.00..563.98 rows=26755 width=0) (actual time=1.527..1.527 rows=24566 loops=1)
                          Index Cond: ((zeitpunkt <= '2018-05-07 00:00:00'::timestamp without time zone) AND (zeitpunkt >= '2018-05-01 00:00:00'::timestamp without time zone))
              ->  Index Only Scan using uq1_wert on wert w  (cost=0.57..126.94 rows=37 width=8) (actual time=0.002..0.002 rows=1 loops=24566)
                    Index Cond: ((aufnehmer_id = 12749) AND (zeitpunkt_id = z.id))
                    Heap Fetches: 15942
Planning time: 0.399 ms
Execution time: 66.339 ms

,大约需要一秒钟。 当结束日期增加一天,并且查询更改为:

... --same as above
and z.zeitpunkt <= ('2018-05-08')::timestamp without time zone
and z.zeitpunkt >= ('2018-05-01')::timestamp without time zone;

查询计划更改为 enter image description here

Aggregate  (cost=3711151.24..3711151.25 rows=1 width=8) (actual time=35601.351..35601.351 rows=1 loops=1)
  ->  Nested Loop  (cost=66264.74..3711104.14 rows=18840 width=0) (actual time=35348.705..35600.192 rows=17612 loops=1)
        ->  Index Only Scan using idx_aufnehmer_id on aufnehmer a  (cost=0.28..8.29 rows=1 width=4) (actual time=0.007..0.010 rows=1 loops=1)
              Index Cond: (id = 12749)
              Heap Fetches: 1
        ->  Hash Join  (cost=66264.47..3710907.45 rows=18840 width=4) (actual time=35348.693..35598.183 rows=17612 loops=1)
              Hash Cond: (w.zeitpunkt_id = z.id)
              ->  Bitmap Heap Scan on wert w  (cost=43133.18..3678947.46 rows=2304078 width=8) (actual time=912.086..35145.680 rows=2334815 loops=1)
                    Recheck Cond: (aufnehmer_id = 12749)
                    Rows Removed by Index Recheck: 205191912
                    Heap Blocks: exact=504397 lossy=1316875
                    ->  Bitmap Index Scan on idx_wert_aufnehmer_id  (cost=0.00..42557.16 rows=2304078 width=0) (actual time=744.144..744.144 rows=2334815 loops=1)
                          Index Cond: (aufnehmer_id = 12749)
              ->  Hash  (cost=22741.12..22741.12 rows=31214 width=4) (actual time=8.909..8.909 rows=27675 loops=1)
                    Buckets: 32768  Batches: 1  Memory Usage: 1229kB
                    ->  Bitmap Heap Scan on zeitpunkt z  (cost=664.37..22741.12 rows=31214 width=4) (actual time=1.822..5.600 rows=27675 loops=1)
                          Recheck Cond: ((zeitpunkt <= '2018-05-08 00:00:00'::timestamp without time zone) AND (zeitpunkt >= '2018-05-01 00:00:00'::timestamp without time zone))
                          Heap Blocks: exact=152
                          ->  Bitmap Index Scan on idx_zeitpunkt_zeitpunkt_order_desc  (cost=0.00..656.57 rows=31214 width=0) (actual time=1.798..1.798 rows=27675 loops=1)
                                Index Cond: ((zeitpunkt <= '2018-05-08 00:00:00'::timestamp without time zone) AND (zeitpunkt >= '2018-05-01 00:00:00'::timestamp without time zone))
Planning time: 0.404 ms
Execution time: 35608.286 ms

执行时间大约要长1000倍。

因此,查询计划程序似乎切换到先加入aufnehmer和wert,这要比先加入zeitpunkt和wert花费更长的时间。

是否知道是否可以强制保留第一个执行计划?我们已经增加了work_mem,但是没有任何区别。

0 个答案:

没有答案