У меня есть таблица с примерно 20 миллионами строк.Ради аргументов, скажем, в таблице есть два столбца - идентификатор и отметка времени.Я пытаюсь подсчитать количество предметов в день.Вот что у меня есть на данный момент.
SELECT DATE(timestamp) AS day, COUNT(*)
FROM actions
WHERE DATE(timestamp) >= '20100101'
AND DATE(timestamp) < '20110101'
GROUP BY day;
Без каких-либо индексов для запуска на моей машине требуется около 30 секунд.Вот результат анализа объяснения:
GroupAggregate (cost=675462.78..676813.42 rows=46532 width=8) (actual time=24467.404..32417.643 rows=346 loops=1)
-> Sort (cost=675462.78..675680.34 rows=87021 width=8) (actual time=24466.730..29071.438 rows=17321121 loops=1)
Sort Key: (date("timestamp"))
Sort Method: external merge Disk: 372496kB
-> Seq Scan on actions (cost=0.00..667133.11 rows=87021 width=8) (actual time=1.981..12368.186 rows=17321121 loops=1)
Filter: ((date("timestamp") >= '2010-01-01'::date) AND (date("timestamp") < '2011-01-01'::date))
Total runtime: 32447.762 ms
Поскольку я вижу последовательное сканирование, я попытался проиндексировать агрегат даты
CREATE INDEX ON actions (DATE(timestamp));
, который снижает скорость примерно на 50%.
HashAggregate (cost=796710.64..796716.19 rows=370 width=8) (actual time=17038.503..17038.590 rows=346 loops=1)
-> Seq Scan on actions (cost=0.00..710202.27 rows=17301674 width=8) (actual time=1.745..12080.877 rows=17321121 loops=1)
Filter: ((date("timestamp") >= '2010-01-01'::date) AND (date("timestamp") < '2011-01-01'::date))
Total runtime: 17038.663 ms
Я новичок в этом бизнесе по оптимизации запросов и не знаю, что делать дальше.Любые подсказки, как я мог заставить этот запрос работать быстрее?
- edit -
Похоже, что я достигаю пределов индексов.Это в значительной степени единственный запрос, который запускается в этой таблице (хотя значения дат меняются).Есть ли способ разделить таблицу?Или создать таблицу кеша со всеми значениями количества?Или есть другие варианты?