Объясните смысл индекса по битовой карте в Postgres

Рейтинг: 0Ответов: 1Опубликовано: 11.03.2023

Помогите разобраться, как устроено индексное сканирование по битовой карте в постгрес? Нашёл вот такое определение

Основная идея индекса на основе битовых карт (bitmap-индекса) состоит в том, что одна и та же битовая карта (последовательность бит) может указывать на диапазон строк, у которых значение bitmap-индекса соответствует значению данной битовой карты. Таким образом, чем больше одна и та же битовая карта содержит указателей на значащие строки и эти указатели максимально компактно упорядочены, тем меньше размер битового индекса и, соответственно, использование данного индекса является более эффективным при доступе к данным с низкой селективностью. То есть битовый индекс не избирателен в отличие от индекса на основе В-дерева.

собственно, может кто-нибудь объяснить этот тип «на пальцах»?

Ответы

▲ 1Принят

Более привычный index scan выдаёт следующий TID (Tuple Identifier) по одному строго по очереди. Получив из index scan очередной TID - идём проверять видимость транзакции для этой строки, доставать остальные поля и проверять остальные условия запроса, если есть. Если строка подходит по условиям - то возвращаем её на вышестоящий узел плана выполнения (или запросившей эти данные программе если выше никого нет). Затем берём из индекса следующий TID.

bitmap index scan сначала получает все подходящие под условие индексного поиска TID из индекса, затем по порядку запрашивает соответствующие блоки самой таблицы. Порядок чтения физически таблицы так получается более предсказуемый, для bitmap index scan можем использовать вызовы posix fadvise для информирования операционной системы, что нам скоро понадобятся вот такие вот блоки (это всё на что действительно влияет настройка effective_io_concurrency), readahead вероятно тоже будет чуть более полезен чем обычно. Промежуточная структура данных, используемая для хранения TID или целых страниц таблицы, которые нужно прочесть из таблицы и называется bitmap.

Что интересно, bitmap index scan может быть lossy. У индекса есть возможность вернуть строки, которые возможно подходят под условие поиска, но это нужно проверить после чтения действительных данных блока. Например, индексный метод brin может сказать "на этой странице данных в таблице есть подходящие записи", но не сказать какие именно, он не хранит сами TID, только номера страниц. При недостатке work_mem bitmap может сам перейти в режим lossy: отметить на битовой карте, что нужно прочитать все строки со страницы и отбросить лишнее - это существенно компактнее по памяти, чем отмечать на битовой карте конкретные строки.

Но при этом bitmap, конечно, вообще не способен возвращать данные в отсортированном виде. Типичный запрос показать "10 последних по дате чего бы то ни было" будет неэффективно выполнять через bitmap (вполне возможно, что seqscan будет даже удобнее), но элементарное действие для index scan.