Поскольку распределение значений неизвестно мне, нет четкого способа решения проблемы.
Но одна проблема очевидна: есть индекс для столбца eventtime, но поскольку запрос работает с функцией над этим столбцом, индекс не может использоваться.
eventtime in time zone 'UTC' > CURRENT_DATE
Либо индекс должен быть отброшен и воссозданы с этой функцией или запрос должен быть переписан.
воссоздают индекс (пример):
CREATE INDEX ON t_el_eventlog (timezone('UTC'::text, eventtime));
(это то же самое, как eventtime in time zone 'UTC'
)
Это соответствует фильтру с помощью функции, индекс может быть использован.
Я подозреваю, что источник не имеет большого распространения, не имея очень разных значений. В этом случае падение индекса на SourceId И сбросив индекс на eventtime с созданием нового индекса по eventtime и SourceId может быть идея:
CREATE INDEX ON t_el_eventlog (timezone('UTC'::text, eventtime), sourceid);
Это то, что теория говорит нам.Я провел несколько тестов по этому поводу, стол с примерно 10 миллионами строк, распределение событий в течение 36 часов и только 20 различных исходников (1..20). Распределение очень случайное. Лучшие результаты были в индексе за время события, sourceid (без индекса функции) и при настройке запроса.
CREATE INDEX ON t_el_eventlog (eventtime, sourceid);
-- make sure there is no index on source id. we need to force postgres to this index.
-- make sure, postgres learns about our index
ANALYZE; VACUUM;
-- use timezone function on current date (guessing timezone is CET)
SELECT * FROM t_el_eventlog
WHERE eventtime > timezone('CET',CURRENT_DATE) AND sourceid = 14;
С таблицей, имеющей 10'000'000 строк, этот запрос возвращает мне около 500 000 рядов всего в 400 мс. (вместо 1400 до 1700 во всех других комбинациях).
Поиск наилучшего соответствия между индексами и запросом - это квест. Я предлагаю некоторые исследования, рекомендация является http://use-the-index-luke.com
это то, что план запроса выглядит с последним подходом:
Index Only Scan using evlog_eventtime_sourceid_idx on evlog (cost=0.45..218195.13 rows=424534 width=0)
Index Cond: ((eventtime > timezone('CET'::text, (('now'::cstring)::date)::timestamp with time zone)) AND (sourceid = 14))
, как вы можете видеть, это идеальный матч ...
Просьба отобразить план (ы) запроса. –
@CraigRinger: я добавил план запроса в указанном выше вопросе – Chanti
, предполагая, что время события находится в utc, просто установите CURRENT_DATE в utc вместо eventtime в CET: SELECT [...] WHERE eventtime> CURRENT_DATE в часовом поясе 'UTC' – byMike