BRIN (Block Range INdex) - радикальный размен точности на размер.
Сводка вместо адресов
Вместо записи на строку BRIN хранит min/max на каждый диапазон блоков
(pages_per_range, по умолчанию 128):
блоки 0-127: min=01-01 max=01-05
блоки 128-255: min=01-05 max=01-09
Поиск отбрасывает диапазоны, чей интервал не содержит искомое; оставшиеся читает Bitmap Heap Scan с recheck (BRIN неточен). Размер растёт с числом диапазонов, не строк - индекс на гигабайтную таблицу умещается в килобайты.
Условие пригодности: корреляция
BRIN полезен, только когда физический порядок строк совпадает с порядком значений. Однострочный тест:
SELECT correlation FROM pg_stats WHERE tablename='events' AND attname='at';
-- около ±1 → BRIN эффективен; около 0 → бесполезен
Идеальный случай - append-only таблица с временем.
Когда вредит
На перемешанных данных min/max каждого диапазона - почти весь домен, сводки ничего не отсекают, и BRIN хуже Seq Scan. UPDATE/DELETE разрушают корреляцию (MVCC кладёт версии в произвольные места), поэтому BRIN держат на таблицах, которые в основном дописываются.
CREATE INDEX ON events USING brin (at);
Точный аналог для произвольных данных - btree-structure; выбор типа - в index-design.