Индексы (Indexes)
Goal
Объяснить какие типы индексов доступны в AngaraBase, когда их использовать и как они взаимодействуют с MVCC.
AngaraTree — index engine
AngaraTree — индексный движок AngaraBase. Индексы хранятся в .atl-файлах отдельно от heap-данных.
B+tree (default)
Основной тип индекса. Подходит для equality- и range-запросов; ключи хранятся в детерминированном порядке.
-- Создание B+tree индекса (эквивалентные формы):
CREATE INDEX idx_name ON orders (customer_id);
CREATE INDEX idx_name ON orders USING btree (customer_id);
B+tree индекс ускоряет:
- Точные совпадения:
WHERE customer_id = 42 - Диапазоны:
WHERE created_at >= '2026-01-01' AND created_at < '2026-02-01' - Сортировку:
ORDER BY customer_id
BRIN (Block Range Index)
Компактный индекс для данных с естественным порядком (append-only, time-series). BRIN хранит min/max значения для диапазонов heap-страниц, что позволяет пропускать целые блоки при сканировании.
CREATE INDEX idx_ts ON events USING brin (created_at);
Поддерживаемые типы ключей:
| Тип | Алиасы |
|---|---|
INTEGER | int, int4 |
BIGINT | int8 |
DATE | — |
TIMESTAMP | — |
TIMESTAMPTZ | — |
Как BRIN работает: индекс выступает как accelerator path — сначала отсекаются блоки, не содержащие нужных значений, затем выполняется heap fetch с MVCC predicate recheck. BRIN не гарантирует точность — он только сужает область поиска.
Метрика эффективности: angara_brin_range_efficiency показывает долю блоков, пропущенных благодаря BRIN.
Чем ближе к 1.0, тем эффективнее индекс (данные хорошо кластеризованы).
Hash / Bloom
Зарезервированы как optional/future index types. На данный момент не реализованы.
Индексы и MVCC
Индекс хранит ссылки TID (page_id, slot_id) на строки в heap. Видимость строки определяется не
индексом, а MVCC-слоем при чтении heap-страницы:
- Запрос обращается к индексу → получает набор TID.
- По каждому TID читается heap-страница.
- MVCC-слой проверяет видимость версии строки для текущей транзакции.
Следствие: индекс может содержать ссылки на невидимые (устаревшие) версии строк. Это нормально — такие записи фильтруются при heap fetch.
IndexStore — персистентные вторичные индексы
AngaraBase поддерживает персистентные вторичные индексы для RowStore таблиц через IndexStore.
Как работает
CREATE INDEXстроит индекс через полный скан таблицы (build_from_rows) и сохраняет результат.- DML (INSERT/DELETE) автоматически обновляет все индексы таблицы — fail-closed: если обновление индекса не удалось, heap mutation откатывается.
- Оптимизатор использует индекс для
WHERE col = valueзапросов (O(log N) вместо O(N) seq_scan).
Ресурсные ограничения
| Ограничение | Конфиг | При нарушении |
|---|---|---|
| Макс. страниц на индекс | storage.max_index_pages_per_table | PageLimitExceeded → DML abort |
| Время обслуживания индекса | storage.index_maintenance_budget_ms (default: 5000ms) | MaintenanceBudgetExceeded → DML abort |
Наблюдаемость
| Метрика | Описание |
|---|---|
angarabase_index_inserts_total | Всего вставок в индекс |
angarabase_index_deletes_total | Всего удалений из индекса |
angarabase_index_reject_total | Отклонённые DML из-за ошибок индекса |
angarabase_index_maintenance_duration_ms | Гистограмма времени обслуживания индекса |
Текущие ограничения
| Ограничение | Статус |
|---|---|
| Только single-column индексы | Текущая версия (v0 bound) |
| Нет partial indexes | Не поддержано (v4 scope) |
| Нет expression indexes | Не поддержано (v4 scope) |
| Нет covering indexes | Не поддержано (v4 scope) |
| Online index build (без блокировки DML) | Не поддержано (H1-v0.7.x) |
| WAL-first для index mutations | In-memory index: восстанавливается через build_from_rows при recovery. Disk-backed WAL-first — в roadmap дальнейших релизов. |
Попытка создать неподдерживаемый индекс возвращает SQLSTATE 0A000 (feature_not_supported).
Когда создавать индексы
Рекомендуется:
- На колонках, часто используемых в
WHERE,JOIN ON,ORDER BY. - BRIN — на time-series колонках таблиц с
append_only = true, где данные вставляются в порядке возрастания ключа.
Не рекомендуется:
- На таблицах с малым количеством строк (full scan будет быстрее).
- На колонках с очень низкой селективностью (например,
boolean-флаги). - Создание множества индексов на одной таблице замедляет
INSERT/UPDATE/DELETE.
Используйте EXPLAIN ANALYZE для проверки, использует ли оптимизатор индекс. Подробнее — Обработка
запросов.
Проверка целостности индекса
Для offline-проверки целостности B+tree индекса доступна функция validate():
SELECT angara_index_validate('idx_name');
Рекомендуется выполнять после аварийного завершения или восстановления из backup.
Связанные разделы
Концепции (что почитать дальше)
- Обработка запросов — как оптимизатор выбирает и комбинирует индексы.
- Хранение данных — как страницы B+tree ложатся в tablespace.
- Транзакции и MVCC — почему обновление индексов под нагрузкой требует MVCC-видимости.
How-to (что сделать)
- DDL: CREATE/DROP INDEX — синтаксис создания и удаления индексов.
- Диагностика — как через
EXPLAIN ANALYZEиsys.*понять, используется ли индекс.
Справочник
- Типы данных — какие типы поддерживаются как ключи индексов.
- Системные представления
sys.*—sys.indexes,sys.column_statsдля анализа покрытия.