Получение строк, которые не обновлялись в течение последних 24 часов - PullRequest
1 голос
/ 21 июня 2020

У меня есть большая таблица (40+ миллионов записей) со следующей структурой:

CREATE TABLE collected_data(
    id TEXT NOT NULL,
    status TEXT NOT NULL,
    PRIMARY KEY(id, status),
    blob JSONB,
    updated_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW()
);

Мне нужно получить все (или, по крайней мере, 100000) записей, которые имеют updated_at старше 24 часов с определенным статусом и имеет большой двоичный объект, который не является нулевым.

Таким образом, запрос становится:

SELECT
    id
FROM
    collected_data
WHERE
    status = 'waiting'
    AND blob IS NOT NULL
    AND updated_at < NOW() - '24 hours'::interval
LIMIT 100000;

В результате получается план выполнения примерно такой: 1011 *

Это почти всегда приводит к полному сканированию таблицы, что означает, что некоторые запросы выполняются очень медленно.

Я пытался создать индексы, такие как CREATE INDEX idx_special ON collected_data(status, updated_at);, но это не помогло.

Можно ли как-нибудь ускорить этот запрос?

1 Ответ

1 голос
/ 21 июня 2020

Планировщик думает, что 25 310 265 строк будут соответствовать вашим условиям, поэтому он считает, что ему не хватит выбора, если с помощью последовательного сканирования получить всего 100 000 строк, а затем преждевременно остановиться. Если на самом деле их не так много или их так много, но все они сгруппированы не в той части таблицы, это на самом деле будет не так быстро. Это особенно вероятно, если после выбора 100 000 из них следующее, что вы сделаете, - это обновите их таким образом, чтобы они больше не соответствовали критериям. Потому что тогда вам придется проходить мимо накапливающихся остатков тех, которые использовались для квалификации, чтобы найти следующую партию.

Вы можете побудить ее использовать индекс, добавив к вашему запросу 'order by updated_at'. Вы также можете сложить колоду в свою пользу, создав частичный индекс CREATE INDEX ON collected_data(status, updated_at) where blob is not null или, возможно, CREATE INDEX ON collected_data(updated_at) where status='waiting' and blob is not null.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...