Запрос Postgresql выполняется медленно - PullRequest
0 голосов
/ 06 марта 2019

У меня есть запрос PostgreSql следующим образом:

SELECT DISTINCT ON (reference) reference, reference_url 
FROM vehicles v 
WHERE NOT EXISTS 
    (select reference 
     from daily_run_vehicle rv 
     WHERE ((
           handled = False 
           AND retries >= 5 ) 
           OR rv.timestamp::timestamp::date = now()::date)  
     AND v.reference=reference);

Где в таблице vehicles около 400 000 записей, а в таблице daily_run_vehicle около 50 миллионов записей.

Таким образом, мне нужны все транспортные средства, для которых это транспортное средство не добавлено в daily_run_vehicle сегодня или где обработанный столбец равен False И повторы column is >= 5.

Но проблема в том, что выполнение запроса занимает много времени.

Есть ли способ написать его лучше, чтобы он выполнялся быстрее?

Ответы [ 2 ]

0 голосов
/ 06 марта 2019

Хммм. Я думаю:

SELECT DISTINCT ON (v.reference) v.reference, v.reference_url 
FROM vehicles v 
WHERE NOT EXISTS (select 1 
                  from daily_run_vehicle rv 
                  where rv.reference = v.reference and
                        rv.handled = False and
                        rv.retries >= 5
                 ) and
      NOT EXISTS (select 1 
                  from daily_run_vehicle rv 
                  where rv.reference = v.reference and
                        rv.timestamp >= current_date::timestamp and
                        rv.timestamp >= (current_date + interval '1 day'::timestamp 
                 )
ORDER BY v.reference;

Для этого запроса вам нужны индексы:

  • daily_run_vehicle(reference, handled, retries)
  • daily_run_vehicle(reference, timestamp)
  • reference_url(reference, reference_url)
0 голосов
/ 06 марта 2019

У меня есть теория, что это может быть связано с вызовом функции now () миллионы раз. Вы можете проверить, запустив этот запрос вместо

SELECT DISTINCT ON (reference) reference, reference_url 
FROM vehicles v 
WHERE NOT EXISTS 
    (select reference 
     from daily_run_vehicle rv 
     WHERE ((
           handled = False 
           AND retries >= 5 ) 
           OR rv.timestamp::timestamp::date = '2019-03-06')  
     AND v.reference=reference);

Если производительность улучшена, вам придется установить сегодняшнюю дату в переменную и использовать переменную в запросе, чтобы сделать только один вызов. В дополнение к этому, если вы используете EXISTS, традиция состоит в том, чтобы выбрать SELECT 1 FROM ... вам не нужны значения, только если есть хотя бы один или нет.

...