@parallel47adm

Как сделать правильный комплексный индекс?

Есть довольно большая таблица (200млн+) в которой есть три интересующие колонки:
update_date timestamptz
num_status int
n_flag int

n_flag может быть 0..5
num_status 0..20
update_date - это когда запись была обновлена.

Надо найти самую старую по обновленности запись, где n_flag=0 и num_status>=10.

Запрос
select * from table1 where n_flag=0 and num_status>=10 order by update_date asc limit 1;
Очень дооолго.

select * from table1 where num_status>=10 order by update_date asc limit 1; - быстро
select * from table1 where n_flag=0 order by update_date asc limit 1; - быстро

На всех трех полях есть индекс.
Как сделать правильно?
  • Вопрос задан
  • 144 просмотра
Решения вопроса 1
Melkij
@Melkij
PostgreSQL DBA
Надо найти самую старую по обновленности запись, где n_flag=0 и num_status>=10.

btree(update_date) where n_flag=0 and num_status>=10
Ответ написан
Пригласить эксперта
Ответы на вопрос 1
@Akina
Сетевой и системный админ, SQL-программист.
n_flag может быть 0..5
num_status 0..20
...
запись, где n_flag=0 и num_status>=10.

Указанным условиям при равномерном распределении значений соответствует ~9% записей, т.е. 18 млн. Причём отбор по n_flag более селективен.
Чисто теоретически оптимальным без использования фич Постгресса будет индекс (n_flag, update_date, num_status).

DEMO fiddle. Правда, 200 млн. записей я генерить как-то не решился... но для 1 млн. записей запрос показывает 40-50 мс - по-моему, вменяемо.

PS. Индекс называется на "комплексный", а композитный. Кроме того, этот индекс - покрывающий, т.е. для обработки запроса серверу не требуется обращаться к таблице.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы