Последовательное сканирование в случае подзапроса PostgreSQL - PullRequest
1 голос
/ 04 октября 2019

У меня есть 2 таблицы:

  1. requests: содержание 60 миллионов записей (используется в качестве журнала для веб-сайта)

  2. requests_hours: содержимое несколько сотен строк (постоянно обновляйте его каждую минуту из requests таблиц)

У меня следующий простой запрос, но когда я его выполняю, он занимает около 5минут, чтобы завершить, потому что Postgres не использует индекс столбца request_time_utc и просто выполняет последовательное сканирование.

SELECT COUNT(request_id)
FROM requests
WHERE request_time_utc >= (SELECT MAX(request_hour_utc) FROM requests_hours)

enter image description here

, но если я просто удалю подзапрос (который сам по себе выполняется за 0,003 с) и заменил его статическим значением, как показано ниже, я получаю следующий запрос, выполненный всего за 0,008 с:

SELECT COUNT(request_id)
FROM requests
WHERE request_time_utc >= '2019-09-30 17:00:00'

enter image description here

Запрос должен подсчитывать всего несколько строк каждую минуту, от 1000 до 7000, поэтому, конечно, сканирование индекса по столбцу request_time_utc должно быть намного лучше, чем последовательное сканирование.

Я не понял, какзаставить PostgreSQL выполнить сканирование индекса для первого запроса.

Вышеуказанные запросыдля упрощения вопроса;вот оригинал:

SELECT 
            customer_id,
            DATE_TRUNC('hour', request_time_utc) AS request_hour_utc,
            COUNT(request_id) AS total_requests,
            SUM(data_in_size) AS total_data_in_size,
            SUM(data_out_size) AS total_data_out_size,
            SUM(process_long) AS total_process_long
            FROM requests
            WHERE request_time_utc >= (SELECT MAX(request_hour_utc) FROM requests_hours)
                        AND customer_id IS NOT NULL
            GROUP BY request_hour_utc , customer_id
            ORDER BY request_hour_utc DESC;

1 Ответ

1 голос
/ 04 октября 2019

Переместите свой подзапрос в CTE, вот так (я пишу это со своего телефона в поезде, поэтому вам нужно будет приземлиться по правильному запросу :-)):

WITH your_max AS (SELECT MAX(request_hour_utc) as foo FROM requests_hours)
SELECT COUNT(request_id)
FROM requests CROSS JOIN your_max
WHERE request_time_utc >= your_max.foo
...