Почему этот запрос не использует индексы, которые я создал?

Запуск postgres 9.5

SELECT events.id, events.start_time, events.host_id, events.title from events
JOIN accountsevents ON accountsevents.events_id = events.id
WHERE accountsevents.accounts_id = %(account_id)s OR events.host_id = %(account_id)s
GROUP BY events.id
ORDER BY start_time DESC

У меня есть этот запрос , индексы : "events_pkey" PRIMARY KEY , ВТКЕЕ ( идентификатор ) ограничения внешнего ключа : "events_host_id_fkey" FOREIGN KEY ( host_id ) Лит счета ( ID ) Реферировано по : СТОЛ "accountsevents" CONSTRAINT "accountsevents_events_id_fkey" FOREIGN KEY ( events_id ) ССЫЛКИ События ( id ) ТАБЛИЦА "eventsinterests" CONSTRAINT "eventsinterests_events_id_fkey" FOREIGN KEY ( events_id ) Лит событий ( идентификаторы ) Индексы : "accountsevents_pkey" PRIMARY KEY , ВТКЕЙ ( идентификатор , accounts_id , events_id ) ограничения внешнего ключа : "accountsevents_accounts_id_fkey" FOREIGN KEY ( accounts_id ) ЛИТЕРАТУРЫ счета ( ID ) «accountsevents_events_id_fkey « FOREIGN KEY ( events_id ) ССЫЛКИ События ( id ) postgres говорят, что стоимость составляет более 100 тыс. Кажется чрезмерным. Это единственный запрос, который у меня есть, который не использует индексы, которые я создал f «Sort (cost = 124388.27..124390.10 rows = 732 width = 40) (фактическое время = 1533.902..1533.928 rows = 470 loops = 1) " " Выход: events.id, events.start_time, events.host_id, events.title " " Ключ сортировки: events.start_time DESC " " Метод сортировки: quicksort Память: 66kB " " -> HashAggregate (стоимость = 124346.12..124353.44 строки = 732 width = 40) (фактическое время = 1533.658..1533.759 rows = 470 loops = 1) " " Выход: events.id, events.start_time, events.host_id, events.title " " Group Key: events.id " " -> Hash Join (стоимость = 4912.30..124344.29 rows = 732 width = 40) (фактическое время = 56.671..1532.831 rows = 971 loops = 1) " " Выход: events.id, events.start_time, events.host_id, события .title " " Hash Cond: (accountsevents.events_id = events.id) " " Присоединиться к фильтру : ((accountsevents.accounts_id = 1) ИЛИ (events.host_id = 1)) " " Строки удалены по фильтру присоединения: 2761882 " " - > Seq Scan on public.accountsevents (cost = 0.00..45228.52 rows = 2762852 width = 8) (фактическое время = 0.005..466.094 rows = 276 2853 loops = 1) " " Выход: accountsevents.events_id, accountsevents.accounts_id " " -> Hash (cost = 2795.91..2795.91 rows = 104191 width = 40) (фактическое время = 53.579..53.579 rows = 104181 loops = 1) " " Output: events.id, events.start_time, events.host_id, events.title " " Ковши: 65536 Партии: 4 Использование памяти: 2462kB " " -> Seq Scan on public.events (cost = 0.00..2795.91 rows = 104191 width = 40) (фактическое время = 0,004..26.171 rows = 104181 loops = 1) " " Выход: events.id, events.start_time, events.host_id, events.title " " Время планирования: 0.201 мс " " Время выполнения : 1534.024 ms " каждая таблица.

OR

Я чувствую, что индекс настроен неверно. ГДЕ Я просто что-то пропустил с запросом. Первоначальные сканирования последовательности убивают его.

ДОБАВЛЕНО ОБЪЯСНЕНИЕ ВЕРБОМ

OR

sql,database,postgresql,postgresql-9.5,

0

Ответов: 1


3 принят

Ни один индекс не поможет вам с этим запросом.

Проблема заключается в том, что у вас есть ORв ANDсостоянии, так что это не представляется возможным применить фильтр перед тем таблицы соединяются, что, где индекс может помочь вам. Попробуйте заменить ORa ANDи посмотреть, как PostgreSQL может сделать намного лучше.

Таким образом, PostgreSQL должен вычислить все соединение и может только отфильтровывать строки после этого - увидеть большое количество строк, удаленных фильтром Join .

Единственное, что может быть использовано для индекса, - это объединение вложенных циклов, и это будет намного дороже. Поэтому я не думаю, что есть лучший план для этого запроса.

Вы можете видеть, что оценки PostgreSQL по количеству строк довольно хороши, что обычно является признаком того, что PostgreSQL действительно поступил правильно.

Возможно, вы можете сделать лучше с помощью запроса типа

SELECT * FROM
   (SELECT ... FROM events JOIN accountsevents ON ...
       WHERE accountsevents.accounts_id = 1
    UNION
    SELECT ... FROM events JOIN accountsevents ON ...
       WHERE events.host_id = 1) sub
GROUP BY ... ORDER BY ...

но я бы не стал спорить об этом.
(Примечание: этот запрос семантически немного отличается, но, возможно, в вашем случае это не имеет значения.)

SQL, базы данных, PostgreSQL, PostgreSQL-9,5,