У меня есть таблица, содержащая столбец timestamp
и столбец source
varchar(20)
. Я вставляю пару тысяч записей в эту таблицу каждый час, и я хотел бы показать совокупность этих данных. Мой запрос выглядит следующим образом:Агрегатный запрос PostgreSQL очень медленный
EXPLAIN (analyze, buffers) SELECT
count(*) AS count
FROM frontend_car c
WHERE date_created at time zone 'cet' > now() at time zone 'cet' - interval '1 week'
GROUP BY source, date_trunc('hour', c.date_created at time zone 'CET')
ORDER BY source ASC, date_trunc('hour', c.date_created at time zone 'CET') DESC
Я уже создал индекс, как так:
create index source_date_created on
table_name(
(date_created AT TIME ZONE 'CET') DESC,
source ASC,
date_trunc('hour', date_created at time zone 'CET') DESC
);
И выход из моих ANALYZE
является:
QUERY PLAN
----------------------------------------------------------------------------------------------------------------------------------------------------------------------
Sort (cost=142888.08..142889.32 rows=495 width=16) (actual time=10242.141..10242.188 rows=494 loops=1)
Sort Key: source, (date_trunc('hour'::text, timezone('CET'::text, date_created)))
Sort Method: quicksort Memory: 63kB
Buffers: shared hit=27575 read=28482
-> HashAggregate (cost=142858.50..142865.93 rows=495 width=16) (actual time=10236.393..10236.516 rows=494 loops=1)
Group Key: source, date_trunc('hour'::text, timezone('CET'::text, date_created))
Buffers: shared hit=27575 read=28482
-> Bitmap Heap Scan on frontend_car c (cost=7654.61..141002.20 rows=247507 width=16) (actual time=427.894..10122.438 rows=249056 loops=1)
Recheck Cond: (timezone('cet'::text, date_created) > (timezone('cet'::text, now()) - '7 days'::interval))
Rows Removed by Index Recheck: 141143
Heap Blocks: exact=27878 lossy=26713
Buffers: shared hit=27575 read=28482
-> Bitmap Index Scan on frontend_car_source_date_created (cost=0.00..7592.74 rows=247507 width=0) (actual time=420.415..420.415 rows=249056 loops=1)
Index Cond: (timezone('cet'::text, date_created) > (timezone('cet'::text, now()) - '7 days'::interval))
Buffers: shared hit=3 read=1463
Planning time: 2.430 ms
Execution time: 10242.379 ms
(17 rows)
Очевидно, что это слишком медленно и на мой взгляд, он должен быть способен вычисляться только с использованием индексов, если я использую только время или источник для агрегации, это достаточно быстро, но вместе как-то медленно.
Это довольно небольшой VPS с 512 МБ оперативной памяти, а база данных в настоящее время содержит около 700 тыс. Строк.
Из того, что я читал, кажется, что большая часть времени тратится на перепроверку, а это значит, что индекс не поместился в память?
Какая у вас настройка 'work_mem' для этого запроса? Можете ли вы увеличить его и перепроверить? – vyegorov
Его по умолчанию 4 МБ, я пытался увеличить до 300 МБ, но безуспешно. – mirosval
Как «Кучи блоков: точное = 27878 lossy = 26713' и' Строки, удаленные с помощью индекса «Повторная проверка индекса»: строки меняются с увеличением 'work_mem'? Я думаю, что, возможно, частичный индекс в вашем предложении 'WHERE' может помочь лучше. – vyegorov