2016-10-11 3 views
0

У меня есть таблица с событиями с first_seen (datetime), last_seen (datetime) и severity (целое число).Оптимизировать таймеры запросов PostgreSQL с интервалами

Я пытаюсь найти, сколько событий были активны в осторожных интервалами 15 минут:

WITH intervals AS 
    (
     SELECT 
     '2016-08-02 00:00:00'::TIMESTAMP 
      + (n||' minutes')::INTERVAL AS start_time, 
     '2016-08-02 00:00:00'::TIMESTAMP 
      + ((n + 15)||' minutes')::INTERVAL AS end_time 
     FROM generate_series(0, 24 * 60, 15) n 
) 
SELECT 
    start_time, 
    (SELECT count(*) FROM event 
    WHERE first_seen < end_time AND last_seen > start_time 
     AND severity = 5) red, 
    (SELECT count(*) FROM event 
    WHERE first_seen < end_time AND last_seen > start_time 
     AND severity = 4) orange, 
    (SELECT count(*) FROM event 
    WHERE first_seen < end_time AND last_seen > start_time 
     AND severity = 3) yellow 
FROM intervals; 

У меня также есть индекс по (first_seen, last_seen, severity).
Моя проблема в том, что она кажется слишком медленной.
Стол имеет около 100 тысяч строк, а для выполнения 100 интервалов - 10 секунд. Сканирование индекса кажется слишком медленным.

Любые идеи по оптимизации этого запроса?

ответ

1

Лучше всего избавиться от подзапросов.

Try что-то вроде следующих (непроверенными, поэтому она может содержать ошибки):

WITH intervals AS 
    (
     SELECT 
     '2016-08-02 00:00:00'::TIMESTAMP 
      + (n||' minutes')::INTERVAL AS start_time, 
     '2016-08-02 00:00:00'::TIMESTAMP 
      + ((n + 15)||' minutes')::INTERVAL AS end_time 
     FROM generate_series(0, 24 * 60, 15) n 
) 
SELECT 
    start_time, 
    sum(CASE WHEN severity = 5 THEN 1 ELSE 0 END) red, 
    sum(CASE WHEN severity = 4 THEN 1 ELSE 0 END) orange, 
    sum(CASE WHEN severity = 3 THEN 1 ELSE 0 END) yellow 
FROM event 
    RIGHT OUTER JOIN intervals 
     ON first_seen < end_time AND last_seen > start_time 
GROUP BY start_time; 
ORDER BY start_time; 

Вы можете быть в состоянии ускорить вещи двух индексов на first_seen и last_seen. Многоколоночный индекс не поможет.

+1

Примечание: generate_series() работает с временными метками, также: 'с интервалами AS (SELECT, гса КАК start_time , Gs + '15 минут КАК END_TIME ОТ generate_series ('2016-08-02 00:00:00' :: TIMESTAMP , '2016-08-03 00:00:00' :: TIMESTAMP , '15 minutes ':: INTERVAL) gs ) ' – joop

+1

Да. Я оставил эту часть, чтобы уменьшить потенциальную путаницу. –

+0

Вау, это в 2 раза быстрее. Спасибо д. – windravenii

Смежные вопросы