← Назад к вопросам

Почему индексы плохо создавать в колоночной бд?

1.3 Junior🔥 41 комментариев
#SQL и базы данных#Хранилища данных

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI26 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Почему индексы неэффективны в колоночных БД

Различие в архитектуре

Строчные БД (Row-oriented) хранят данные по строкам:

Таблица Users:
Row 1: id=1, name="Alice", age=30, salary=50000
Row 2: id=2, name="Bob", age=25, salary=45000

Колоночные БД (Column-oriented) хранят данные по колонкам:

Таблица Users в колоночном формате:
id:     [1, 2, 3, ...]
name:   ["Alice", "Bob", ...]
age:    [30, 25, ...]
salary: [50000, 45000, ...]

Почему индексы плохо работают в колоночных БД

1. Весь столбец уже отсортирован

Колоночные БД хранят значения отсортированными:

-- В ClickHouse, Vertica, Parquet
-- Если читать column age, он уже отсортирован
SELECT * FROM users WHERE age > 25;
-- Работает за O(log N) через бинарный поиск БЕЗ индекса!

Индекс дублировал бы то, что уже есть.

2. Сжатие данных

Колоночные БД агрессивно сжимают данные (обычно 10-100x):

Основной столбец age: [30, 30, 30, 25, 25, ...] → Run-Length Encoding
→ {value: 30, count: 3}, {value: 25, count: 2}

Индекс занял бы ещё больше места!

3. Batch обработка

Колоночные БД оптимизированы на SIMD и batch обработку:

# Вместо поиска одной записи через индекс
WHERE age = 30

# Обрабатываются целые блоки за раз (1000+ элементов)
# CPU кеш становится важнее, чем индекс
age_batch = [30, 30, 25, 30, 25, 30, ...]
mask = vectorized_compare(age_batch, 30)  # Очень быстро

4. Неуместность традиционных индексов

B-Tree индекс для строчной БД:

Нужно быстро найти 1 запись из миллионов
→ B-Tree срезает время поиска

Колоночная БД:

Нужно найти 1M из 1B записей
→ B-Tree гораздо менее полезен
→ Проще отфильтровать весь столбец vectorized методом

5. Вектоинизация и SIMD

Современные колоночные БД (DuckDB, Polars) используют SIMD инструкции:

-- DuckDB (колоночная БД)
SELECT * FROM sales WHERE amount > 1000;

-- Обрабатывает 256+ значений за одну CPU инструкцию
-- Индекс только замедлит!

Когда колоночные БД используют индексы?

Некоторые колоночные БД ограниченно поддерживают индексы:

ClickHouse:

-- Skip Index (пропускает блоки данных)
CREATE TABLE users (
    id UInt32,
    age UInt32,
    INDEX age_idx age TYPE minmax GRANULARITY 8192
) ENGINE = MergeTree();

Но это не B-Tree, а Skip Index для метаданных блоков.

Сравнение: строчная vs колоночная

ОперацияСтрочная БДКолоночная БД
Найти 1 запись по IDИндекс ускоритИндекс не нужен
Найти 1M по условиюИндекс помогаетVectorized быстрее
Сумма по столбцуНужна таблицаЕстественно быстро
Вставка 1 строкиБыстроМедленнее (batch)
Обновление 1 поляБыстроПерезапись блока

Пример реальной производительности

-- DuckDB (колоночная)
SELECT COUNT(*) FROM users WHERE age > 25 AND salary < 100000;
-- Время: 0.01 сек на 1 млрд строк (без индексов!)

-- PostgreSQL (строчная)
SELECT COUNT(*) FROM users WHERE age > 25 AND salary < 100000;
-- Время: 1+ сек без индексов, 0.001 сек с индексами

Вывод

Индексы в колоночных БД плохи потому что:

  1. Данные уже отсортированы и сжаты
  2. Vectorized сканирование быстрее индекса
  3. Индексы требуют доп. памяти (противоречит цели сжатия)
  4. Оптимизатор лучше работает без индексов
  5. Batch обработка менее совместима с поиском по индексу

Колоночные БД оптимизированы на аналитические запросы над большими наборами данных, где индексы просто не помогают.