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

Что в OLAP бд используется вместо индексов для оптимизации поиска?

1.0 Junior🔥 241 комментариев
#SQL и базы данных

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

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

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

Что в OLAP БД используется вместо индексов для оптимизации поиска?

В OLAP (Online Analytical Processing) базах данных используются совершенно другие подходы к оптимизации поиска, чем в традиционных OLTP системах. Вместо индексов применяются специализированные техники, оптимизированные для аналитических запросов с полными сканированиями больших объёмов данных.

1. Agregation (Агрегация и предвычисление)

Это основной метод оптимизации в OLAP.

Вместо индексов OLAP БД используют предвычисленные агрегации (fact tables с различными уровнями гранулярности).

-- Исходная детальная таблица (fact table)
CREATE TABLE sales_detail (
    transaction_id INT,
    product_id INT,
    customer_id INT,
    store_id INT,
    date_id INT,
    amount DECIMAL(10, 2)
);
-- Размер: 10 миллиардов строк, 1 TB

-- Предвычисленная агрегация по дням
CREATE TABLE sales_by_day (
    date_id INT,
    product_id INT,
    store_id INT,
    total_sales DECIMAL(12, 2),
    transaction_count INT
);
-- Размер: 1 миллион строк, 100 MB

-- Вместо сканирования 1 TB для ответа на запрос:
-- SELECT SUM(amount) FROM sales_detail WHERE date_id = 20240101
-- Просто скорее сканируем 100 MB агрегированной таблицы!

SELECT SUM(total_sales) FROM sales_by_day WHERE date_id = 20240101;

2. Column-oriented Storage (Колончатое хранилище)

Основное отличие OLAP от OLTP.

Данные хранятся по колонкам, а не по строкам. Это позволяет:

  • Читать только необходимые колонки
  • Лучше компрессировать данные (одинаковые значения в колонке сжимаются эффективнее)
  • Параллелизировать обработку
ОЛТП (Row-oriented):
Transaction 1: [ID=1, Name=John, Age=30, Salary=50000, Dept=Sales, ...]
Transaction 2: [ID=2, Name=Jane, Age=28, Salary=55000, Dept=Engineering, ...]

Все данные строки в одном месте памяти

ОЛАП (Column-oriented):
ID Column:     [1, 2, 3, 4, 5, ...]
Name Column:   [John, Jane, Bob, ...]
Age Column:    [30, 28, 35, ...]
Salary Column: [50000, 55000, 60000, ...]

Для запроса SELECT AVG(Age) — читаем ТОЛЬКО Age колонку!

Примеры OLAP БД с column-oriented хранилищем:

  • ClickHouse — на 100% column-oriented
  • Parquet формат — для column-oriented данных
  • Apache Cassandra — можно настроить

3. Compression (Сжатие данных)

ОЛАП базы используют специализированные алгоритмы сжатия, которые работают лучше на column-oriented данных:

Оригинальные данные (Age column):
[30, 30, 30, 28, 28, 35, 35, 35, 35, ...]

RLE (Run-Length Encoding):
(30, 3 раза), (28, 2 раза), (35, 4 раза) — 10x сжатие!

Dictionary encoding для String колонок:
Depт values: ['Sales', 'Engineering', 'Marketing']
Храним: [0, 0, 1, 1, 2, ...] вместо строк

Результат: 1 TB данных → 50-100 GB после сжатия

4. Partitioning (Партиционирование)

Данные разделяются на меньшие части по ключевым колонкам (usually time-based).

-- Партиционирование по дате
CREATE TABLE sales (
    transaction_id INT,
    product_id INT,
    amount DECIMAL,
    date DATE
)
PARTITION BY RANGE (YEAR(date)) (
    PARTITION p2022 VALUES LESS THAN (2023),
    PARTITION p2023 VALUES LESS THAN (2024),
    PARTITION p2024 VALUES LESS THAN (2025)
);

-- Запрос по 2024 году сканирует только partition p2024!
SELECT * FROM sales WHERE date >= '2024-01-01' AND date < '2025-01-01';
-- Сканирование: 100 GB вместо 1 TB = 10x ускорение

5. Bitmap Indexes (Битовые индексы)

Вместо B-tree индексов, используются битовые карты для низкокардинальных колонок (мало уникальных значений).

Традиционный индекс (B-tree):
Department: [Sales] → [1, 5, 7, 23, 45, ...]
            [Engineering] → [2, 4, 8, 15, ...]
            [Marketing] → [3, 6, 9, ...]

Bitmap Index:
Sales:       [1, 0, 0, 1, 0, 0, 0, 1, ...] (16 GB vs 1 GB!)
Engineering: [0, 1, 0, 0, 1, 0, 0, 0, ...]
Marketing:   [0, 0, 1, 0, 0, 1, 0, 0, ...]

Для запроса: SELECT COUNT(*) FROM employees WHERE department IN ('Sales', 'Engineering')
Просто OR'им два bitmap'а!

6. Metadata и Statistics

ОЛАП БД хранят богатую статистику для оптимизации плана запроса:

Для каждого partition/segment:
- Min/Max values (для pruning)
- Row count
- Distinct value count (cardinality)
- Null count

Примеры:
Partition 2024-01-01:
  product_id: min=1, max=500, count_distinct=450
  amount: min=0.50, max=9999.99

Запрос: SELECT COUNT(*) FROM sales WHERE product_id = 1001
Оптимизатор сразу видит: product_id max = 500, значит partition не содержит 1001
Партиция полностью пропускается (partition pruning)!

7. Материализованные представления (Materialized Views)

Предвычисленные результаты популярных запросов.

CREATE MATERIALIZED VIEW sales_by_category_and_date AS
SELECT 
    category_id,
    DATE(order_date) as date,
    SUM(amount) as total_sales,
    COUNT(*) as orders
FROM orders
GROUP BY category_id, DATE(order_date);

-- При запросе этого вида, БД использует materialized view
-- вместо пересчёта всех данных!
SELECT * FROM sales_by_category_and_date WHERE date = '2024-01-01';

8. Projection (Проекции)

В некоторых OLAP БД (Vertica, Greenplum) используются проекции — альтернативные представления данных оптимизированные для конкретных запросов.

Основная таблица: sales(transaction_id, product_id, customer_id, amount, date)

Проекция 1 (для запросов по дате):
Ордер: [date, product_id, amount]
Компрессия: RLE по date

Проекция 2 (для запросов по customer):
Ордер: [customer_id, date, amount]

Запрос SELECT SUM(amount) FROM sales WHERE date = '2024-01-01'
Использует Проекцию 1 — намного быстрее!

Сравнение: OLTP vs OLAP

АспектOLTP (SQL)OLAP (DW)
ХранениеRow-orientedColumn-oriented
ИндексыB-tree, HashBitmap, минимальные
ОптимизацияДля single rowsДля агрегаций
СжатиеМинимальноеМаксимальное (10x)
ПартицииОпциональноОбязательно
АгрегацииOn-the-flyПредвычислены
ОбновленияЧастыеРедкие (batch)
ЗапросыМало данных, быстроМного данных, медленнее
ПримерыPostgreSQL, MySQLSnowflake, BigQuery, ClickHouse

Практический пример: ClickHouse

-- Column-oriented, с автоматическим partition pruning
CREATE TABLE events (
    timestamp DateTime,
    user_id UInt32,
    event_type String,
    properties String
)
ENGINE = MergeTree()
ORDER BY (timestamp, user_id)
PARTITION BY toDate(timestamp);

-- Вставляем 1 миллиард событий
INSERT INTO events SELECT ...

-- Запрос сканирует только partition за 2024-01-01
SELECT 
    event_type,
    COUNT(*) as count
FROM events
WHERE timestamp >= '2024-01-01' AND timestamp < '2024-01-02'
GROUP BY event_type;

-- Время выполнения: < 100 ms вместо минут на традиционной БД

Когда использовать OLAP техники

OLAP (column-oriented, агрегации):

  • Аналитические запросы (SUM, AVG, COUNT)
  • Полное сканирование больших таблиц
  • Данные, обновляемые batch'ами (раз в день/час)
  • Экспад/Snowflake/BigQuery/ClickHouse

OLTP (row-oriented, индексы):

  • CRUD операции на single rows
  • Частые обновления
  • Транзакции (ACID)
  • PostgreSQL/MySQL/Oracle

Вывод

Вместо индексов OLAP БД используют:**

  1. Партиционирование — исключают ненужные данные
  2. Агрегацию — предвычисляют результаты
  3. Column-oriented хранилище — читают только нужные колонки
  4. Сжатие — уменьшают объём данных в памяти
  5. Bitmap индексы — для низкокардинальных колонок
  6. Statistics — для умного pruning

Это позволяет обрабатывать петабайты данных за считанные секунды вместо минут/часов на традиционных системах с индексами.

Что в OLAP бд используется вместо индексов для оптимизации поиска? | PrepBro