PostgreSQL Query без WHERE только ORDER BY и LIMIT не использует индекс - PullRequest
0 голосов
/ 30 мая 2018

У меня есть таблица, которая содержит столбец 'id' типа BIGSERIAL.У меня также есть индекс для этого одного столбца (порядок сортировки по убыванию, BTREE, уникальный).

Мне часто нужно извлечь последние 10, 20, 30 записей из таблицы миллионов записей, например:

SELECT * FROM table ORDER BY id DESC LIMIT 10

Я бы подумал, что это довольно ясный случай: для этого конкретного поля есть индекс, порядок сортировки соответствует, и мне нужно всего 10 записей по сравнению с миллионами во всей таблице, этот запрос определенно использует индекссканирования.

Но он не выполняет последовательное сканирование всей таблицы.

Я стараюсь копать глубже, не нашел ничего необычного.Документ Postgres по адресу https://www.postgresql.org/docs/9.6/static/indexes-ordering.html говорит:

Важным частным случаем является ORDER BY в сочетании с LIMIT n: явная сортировка должна обрабатывать все данные, чтобы идентифицировать первые n строк, но если есть индекс, соответствующий ORDER BY, первые n строк могут быть получены напрямую, без сканирования оставшейся части.

Но это все равно не работает.У кого-нибудь есть какие-нибудь указатели для меня?Может быть, я просто больше не вижу леса для деревьев ...: - (

Ответы [ 2 ]

0 голосов
/ 30 мая 2018

Хорошо, произнесение этого вслух и попытка собрать больше информации для моего вопроса, по-видимому, заставило меня снова увидеть Форрест, я обнаружил реальную проблему.Далее в документе, который я упомянул выше, это предложение:

Индекс, сохраненный в порядке возрастания с нулевыми первыми, может удовлетворять либо ORDER BY x ASC NULLS FIRST, либо ORDER BY x DESC NULLS LAST в зависимости от того, в каком направлениионо сканируется в.

Это была проблема.Я указал порядок сортировки в индексе, но проигнорировал NULLS FIRST vs. LAST.

Postgres по умолчанию равен NULLS FIRST, если вы не упомянули это явно в своем запросе.Так что Postgres обнаружил комбинацию ORDER BY DESC NULLS FIRST, которая не была охвачена моим индексом.Это то, что имеет значение как в SORT ORDER, так и в NULLS.

2 возможных решения:

  • В запросе укажите соответственно NULLS FIRST / LAST, чтобы он соответствовал индексу
  • ... или измените индекс на NULLS FIRST (что я и сделал)

Теперь Postgres выполняет правильное сканирование индекса и во время запроса касается только 10 элементов, а не всехих.

0 голосов
/ 30 мая 2018

Если вам нужно получить последние 10 записей в таблице, вы можете использовать это:

SELECT * 
FROM table 
WHERE id >= (SELECT MAX(id) FROM table) - 10 
ORDER BY id DESC

И аналогично для 20 и 30 записей.Это выглядит не так ясно, но работает быстро, пока у вас есть индекс для столбца 'id'.

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