Comments 14
Я не понял... в финальном запросе равенство вижу (на самом деле равенство по (sender_id, payment_type) = (444, 'СБП')
), диапазон вижу (transaction_date < '2025-05-18' AND transaction_date > '2020-04-18'
)... а где обещанная сортировка?
Спасибо за замечание! Действительно, в финальном запросе используются равенства по (sender_id, payment_type)
и диапазон по transaction_date
, а явной сортировки (ORDER BY
) в SQL-запросе нет.
Однако правило ESR (Equality → Sort → Range) применяется не к самому синтаксису запроса, а к логике построения составного B-tree индекса.
Под Sort здесь понимаются не только поля, указанные в ORDER BY
, а вообще колонки, по которым может быть необходим упорядоченный обход — например, для работы с диапазонами или оптимизации последовательного доступа. Это особенно актуально, когда такие поля используются для отчетов или фильтров по времени.
В нашем случае порядок (sender_id, payment_type, transaction_date)
соответствует схеме E → E → R (два равенства и один диапазон), что полностью соответствует ESR и позволяет PostgreSQL эффективно "обрезать" лишние страницы в глубине индекса при чтении.
Сортировку (ORDER BY
) при желании можно добавить — и этот же индекс сработает корректно, потому что он уже построен в нужном порядке.
Я намеренно сосредоточился на структуре индекса, а не конкретной форме запроса, чтобы показать, в чём суть ESR и почему это работает.
Ну и финально: ESR — это общее практическое правило, применимое к широкому классу запросов, а не к одному конкретному синтаксису.
Ну так вы по сути-то ничего и НЕ показали. Точнее, показали какой-то кусок, обрывок.
Под Sort здесь понимаются не только поля, указанные в
ORDER BY
, а вообще колонки, по которым может быть необходим упорядоченный обход — например, для работы с диапазонами или оптимизации последовательного доступа.
Это - вопрос "включать или не включать поле в индекс". А вот как оно работает на именно последовательности Equality → Sort → Range, а не на совокупности Equality + Sort + Range, вы не показали. И как по мне - на текущий момент цель не достигнуто, а фактическое содержание не соответствует заявленному.
Уж если взялись - то показывайте, как работают ВСЕ компоненты правила. И главным образом - что сортировка перед фильтрацией по диапазону эффективнее, чем после. А желательно - ещё и с указанием, когда эта эмпирика не выполняется.
Вы, кажется, несколько переоцениваете формат статьи. Это практический материал — не технический стандарт и не академическая диссертация. ESR раскрыт в контексте задач, с которыми сталкиваются разработчики в реальных проектах, а не в рамках лабораторной работы на тему "распиши каждую букву".
Заявленная цель — показать, как порядок колонок в индексе влияет на производительность. Это показано. Конкретные значения, планы, замеры — всё на месте. Если вы ожидали чего-то другого — возможно, у вас были другие ожидания, а не у статьи другие цели.
И, честно говоря, разбирать "когда эмпирика не работает" — это уже задача читателя, если он претендует на уровень выше среднего. Материал и так даёт больше, чем большинство туторсов.
Так что если вы не нашли здесь то, что хотели — вполне возможно, вам просто не сюда)
Это показано.
Как по мне, то показано только то, что он - влияет. Как (эмпирика процесса), а уж тем более почему (физика процесса) - практически не затронуто.
А если по вашему мнению ответ на вопрос "как" - это просто выбор одного из вариантов "ускоряет", "замедляет" и "не влияет", пусть и с экспериментальным подтверждением,- то мы с вами и правда по-разному мыслим.
Если вы ожидали формального анализа с доказательствами на уровне оптимизатора — это скорее вопрос не к статье, а к вашим ожиданиям от неё.
https://github.com/postgres/postgres/tree/master/src/backend/access/nbtree - прошу)
Ну я как-то ожидал как минимум полного перебора всех вариантов наличия и порядка полей в индексе. Наличия в таблице полей, отвечающих каждому пункту ESR, и тайминга для всех возможных индексов и без индекса вообще - это как минимум. Причём строго на таблице с одним и тем же наполнением. Ну и планы посмотреть - а что собственно сервер с индексом делал, что именно применял. Даже анализ результатов на читателя можно спихнуть, и ограничиться финальным выводом - и то хорошо бы получилось...
Оптимальным было бы, конечно, сначала создать наполненную данными таблицу со всеми вариациями индексов, а потом прогнать по ней запросы, указывая хинтами использование строго определённого индекса, но, емнип, в Постгрессе таких хинтов пока что не завезли.
Спасибо за статью, познавательно. Мне показалось что зря не покрыли ещё опцию Using
при создании индекса. Пусть он и не участвует в описанных случаях, но тоже полезная инфа по работе с индексами.
Спасибо. Больше деталей с визуализациями можно найти в https://habr.com/ru/companies/tensor/articles/488104/
Во-первых, в листах лежат указатели на записи.
Во-вторых, bitmap index scan возвращает указатели на страницы, на которых будут данные.
В-третьих, если поле в индексе, то оно там отсортировано уже. Идёт оно в начале или в конце не важно.
В-четвертых, поля в индексе должны идти по силе селективности. Самое не уникальное поле самое первое, т.д.
Во-первых, добрый день)
На первые два пункта я не возражаю — да, но значения также лежат.
На третий пункт прошу ещё раз прочитать мою статью: PostgreSQL не покажет и не напишет, какие поля он отсеял, а какие нет.
Четвёртый пункт будет следствием из других. Я не отрицаю селективность, а лишь дополняю её, причём с примером.
Добра вам!
Правильный порядок колонок в B-tree индексах PostgreSQL или правило ESR