У меня есть следующая таблица, которая разбита на основе диапазона дат:
create table volume (
id bigint,
event_ts timestamptz,
lane integer,
measure_line integer,
volume integer,
) partition by range (event_ts)
Я создал запрос, который суммирует объемы для заданных дорожек на некоторой мере measure_line с интервалами в 15 минут:
with time_interval as (
SELECT start_time, start_time + interval '15 minute' as end_time
FROM generate_series( to_timestamp(1561496400), to_timestamp(1561582799), '15 minute'::interval) as start_time
)
select
extract('epoch' from f.start_time)::int as start_time,
coalesce(sum(volume), 0) as volume
from volume v
right join time_interval f
on v.event_ts > f.start_time and v.event_ts < f.end_time
and v.measure_line = 1
and lane in (1,2,3,4)
group by f.start_time, f.end_time
order by start_time;
Существует несколько разделов, по одному на каждый день:
...
volume_20190509
volume_20190510
volume_20190511
...
Для каждого раздела создается следующий составной индекс:
volume_20190518_event_ts_lane_measure_line_idx
Результат запроса выглядит следующим образом:
start_time volume_count
1561496400 58
1561497300 47
1561498200 43
1561499100 49
1561500000 39
1561500900 41
1561501800 47
1561502700 28
1561503600 41
В зависимости от количества параметров в предложении IN для столбца дорожки
postgres использует либо последовательное сканирование, либо созданный индекс (я проверил это с помощью пункта объяснения). Когда он решает использовать последовательное сканирование, запрос замедляется как минимум в 10 раз! Я не могу понять это поведение! Нет очевидной причины, по которой он не всегда должен использовать созданный индекс. У вас есть идеи, почему?
Версия Postgres: PostgreSQL 10.4
Например, когда я передаю только одно значение - где полоса в (1) использует последовательное сканирование. Когда я передаю больше значений - где Lane в (1,2,3,4) он использует созданный индекс.
EDIT:
Объяснить план мероприятий
где переулок в (1,2,3,4)
ОБЪЯСНИТЬ (АНАЛИЗ, БУФЕРЫ)
-> HashAggregate (cost=28395929.50..28395932.50 rows=200 width=28) (actual time=607.714..608.083 rows=96 loops=1)
Group Key: f.start_time, f.end_time
Buffers: shared hit=31658
-> Nested Loop Left Join (cost=0.42..26014632.00 rows=317506333 width=20) (actual time=1.607..514.124 rows=28630 loops=1)
Buffers: shared hit=31658
-> CTE Scan on time_interval f (cost=0.00..20.00 rows=1000 width=16) (actual time=0.057..0.977 rows=96 loops=1)
-> Append (cost=0.42..22839.33 rows=317528 width=12) (actual time=1.068..3.957 rows=298 loops=96)
Buffers: shared hit=31658
-> Index Scan using volume_20190324_event_ts_lane_measure_line_idx on volume_20190324 v (cost=0.42..229.75 rows=3222 width=12) (actual time=0.008..0.008 rows=0 loops=96)
Index Cond: ((event_ts > f.start_time) AND (event_ts < f.end_time) AND (measure_line = 1))
Filter: (lane = ANY ('{1,2,3,4}'::integer[]))
Buffers: shared hit=288
-> Index Scan using volume_20190325_event_ts_lane_measure_line_idx on volume_20190325 v_1 (cost=0.42..228.74 rows=3162 width=12) (actual time=0.008..0.008 rows=0 loops=96)
Index Cond: ((event_ts > f.start_time) AND (event_ts < f.end_time) AND (measure_line = 1))
Filter: (lane = ANY ('{1,2,3,4}'::integer[]))
Buffers: shared hit=288
-> Index Scan using volume_20190326_event_ts_lane_measure_line_idx on volume_20190326 v_2 (cost=0.42..226.53 rows=3122 width=12) (actual time=0.007..0.007 rows=0 loops=96)
Index Cond: ((event_ts > f.start_time) AND (event_ts < f.end_time) AND (measure_line = 1))
Filter: (lane = ANY ('{1,2,3,4}'::integer[]))
Buffers: shared hit=288
-> Index Scan using volume_20190327_event_ts_lane_measure_line_idx on volume_20190327 v_3 (cost=0.42..229.48 rows=3157 width=12) (actual time=0.016..0.016 rows=0 loops=96)
Index Cond: ((event_ts > f.start_time) AND (event_ts < f.end_time) AND (measure_line = 1))
Filter: (lane = ANY ('{1,2,3,4}'::integer[]))
Buffers: shared hit=288
-> Index Scan using volume_20190328_event_ts_lane_measure_line_idx on volume_20190328 v_4 (cost=0.42..228.97 rows=3157 width=12) (actual time=0.007..0.007 rows=0 loops=96)
Index Cond: ((event_ts > f.start_time) AND (event_ts < f.end_time) AND (measure_line = 1))
Filter: (lane = ANY ('{1,2,3,4}'::integer[]))
Buffers: shared hit=288
-> Index Scan using volume_20190329_event_ts_lane_measure_line_idx on volume_20190329 v_5 (cost=0.42..230.02 rows=3227 width=12) (actual time=0.007..0.007 rows=0 loops=96)
Index Cond: ((event_ts > f.start_time) AND (event_ts < f.end_time) AND (measure_line = 1))
Filter: (lane = ANY ('{1,2,3,4}'::integer[]))
Buffers: shared hit=288
...
где переулок в (1) - заняло 5 минут для завершения
Sort (cost=16986442.13..16986442.63 rows=200 width=28) (actual time=332823.872..332824.048 rows=96 loops=1)
Sort Key: f.start_time
Sort Method: quicksort Memory: 32kB
Buffers: shared hit=24 read=113392, temp read=215935 written=2272
CTE time_interval
-> Function Scan on generate_series start_time (cost=0.00..12.50 rows=1000 width=16) (actual time=0.045..0.482 rows=96 loops=1)
-> HashAggregate (cost=16986418.98..16986421.98 rows=200 width=28) (actual time=332823.319..332823.630 rows=96 loops=1)
Group Key: f.start_time, f.end_time
Buffers: shared hit=24 read=113392, temp read=215935 written=2272
-> Nested Loop Left Join (cost=0.00..16386221.49 rows=80026333 width=20) (actual time=12066.893..332801.773 rows=7190 loops=1)
Join Filter: ((v.event_ts > f.start_time) AND (v.event_ts < f.end_time))
Rows Removed by Join Filter: 68689930
Buffers: shared hit=24 read=113392, temp read=215935 written=2272
-> CTE Scan on time_interval f (cost=0.00..20.00 rows=1000 width=16) (actual time=0.058..1.258 rows=96 loops=1)
-> Materialize (cost=0.00..270371.58 rows=720237 width=12) (actual time=0.012..1865.908 rows=715595 loops=96)
Buffers: shared hit=24 read=113392, temp read=215935 written=2272
-> Append (cost=0.00..263253.39 rows=720237 width=12) (actual time=0.115..7524.225 rows=715595 loops=1)
Buffers: shared hit=24 read=113392
-> Seq Scan on volume_20190324 v (cost=0.00..2649.35 rows=7263 width=12) (actual time=0.107..83.392 rows=7205 loops=1)
Filter: ((measure_line = 1) AND (lane = 1))
Rows Removed by Filter: 93285
Buffers: shared hit=1 read=1141
-> Seq Scan on volume_20190325 v_1 (cost=0.00..2644.50 rows=7276 width=12) (actual time=0.047..115.813 rows=7190 loops=1)
Filter: ((measure_line = 1) AND (lane = 1))
Rows Removed by Filter: 93110
Buffers: shared hit=1 read=1139
-> Seq Scan on volume_20190326 v_2 (cost=0.00..2618.95 rows=7002 width=12) (actual time=0.049..77.066 rows=7105 loops=1)
Filter: ((measure_line = 1) AND (lane = 1))
Rows Removed by Filter: 92225
Buffers: shared hit=1 read=1128
-> Seq Scan on volume_20190327 v_3 (cost=0.00..2644.05 rows=7190 width=12) (actual time=0.041..62.538 rows=7195 loops=1)
Filter: ((measure_line = 1) AND (lane = 1))
Rows Removed by Filter: 93075
Buffers: shared hit=1 read=1139
-> Seq Scan on volume_20190328 v_4 (cost=0.00..2644.05 rows=7127 width=12) (actual time=0.026..44.041 rows=7200 loops=1)
Filter: ((measure_line = 1) AND (lane = 1))
Rows Removed by Filter: 93070
Buffers: shared hit=1 read=1139
-> Seq Scan on volume_20190329 v_5 (cost=0.00..2643.90 rows=7236 width=12) (actual time=0.039..44.562 rows=7205 loops=1)
...