0

我们有一个包含测量数据的 db (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;

产生这个查询计划: 在此处输入图像描述

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;

查询计划更改为 在此处输入图像描述

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 但它没有任何区别。

4

0 回答 0