Движок MergeTree — это основной движок хранения в ClickHouse, оптимизированный для быстрого выполнения аналитических запросов на больших наборах данных. Он достигает высокой скорости выполнения запросов благодаря столбцовому хранению, сортировке по первичному ключу, разреженной индексации, фоновому слиянию, партиционированию и сжатию.
1. Ключевые оптимизации в MergeTree для производительности запросов
Особенность оптимизации | Как это улучшает производительность запросов |
---|---|
Столбцовое хранение | Запросы читают только необходимые столбцы, что снижает диск I/O |
Сортировка по первичному ключу | Данные физически упорядочены, что ускоряет запросы по диапазону |
Разреженная индексация | Минимизирует использование памяти, обеспечивая быстрый поиск |
Партиционирование | Пропускает нерелевантные данные, уменьшая время выполнения запросов |
Сжатие данных | Снижает объем хранимых данных и улучшает эффективность I/O |
Фоновое слияние | Оптимизирует хранение данных со временем, ускоряя выполнение запросов |
Векторизованное выполнение | Использует SIMD инструкции для параллельной обработки |
2. Столбцовое хранение для быстрого чтения
В отличие от баз данных на основе строк (MySQL, PostgreSQL), ClickHouse хранит данные в столбцах, а не в строках.
- Запросы читают только нужные столбцы, что снижает диск I/O.
- Эффективное сжатие применяется для каждого столбца.
Пример: Запрос только одного столбца
`SELECT SUM(revenue) FROM sales WHERE event_time >= '2024-01-01';`
В хранилище на основе строк запрос сканирует все столбцы (что увеличивает I/O).
В MergeTree (столбцовое хранение) ClickHouse читает только столбец revenue
→ значительно быстрее!
3. Сортировка по первичному ключу и разреженная индексация
Как это работает:
- Данные хранятся отсортированными по первичному ключу.
- ClickHouse создает разреженный индекс, указывающий на каждую N-ю гранулу.
Пример: Поиск по индексу MergeTree
CREATE TABLE sales (
id UInt32,
event_time DateTime,
revenue Float64
) ENGINE = MergeTree()
ORDER BY (event_time, id);
- Данные физически упорядочены по
event_time
. - Запросы, фильтрующие по
event_time
, сканируют только релевантные секции.
✅ Быстрая фильтрация по диапазону
✅ Меньше использования памяти (поскольку хранится только разреженный индекс)
4. Партиционирование: снижение объема сканируемых данных
MergeTree поддерживает партиционирование, позволяя запросам пропускать целые партиции.
Пример: Создание партиционированной таблицы
CREATE TABLE sales (
id UInt32,
event_time DateTime,
revenue Float64
) ENGINE = MergeTree()
PARTITION BY toYYYYMM(event_time)
ORDER BY (event_time, id);
- Партиционирование по месяцам означает, что запрос для января 2024 года сканирует только 1/12 данных.
✅ Значительное сокращение времени выполнения запроса
✅ Легко удалять партиции для соблюдения политик хранения данных
5. Фоновое слияние для оптимизации хранения
Как работает слияние:
- Данные записываются в мелкие части.
- Процесс фонового слияния периодически объединяет их в более крупные и оптимизированные части.
- Это поддерживает эффективное хранение и предотвращает фрагментацию.
✅ Ускоряет запросы за счет уменьшения числа мелких, неэффективных файлов
✅ Обеспечивает оптимальную скорость чтения со временем
6. Сжатие: снижение объема хранения и улучшение скорости запросов
MergeTree поддерживает несколько алгоритмов сжатия:
Алгоритм сжатия | Лучше всего для | Как работает |
---|---|---|
LZ4 (по умолчанию) | Общего назначения | Быстрое сжатие/распаковка, низкое использование процессора |
ZSTD (Zstandard) | Высокое сжатие | Более ресурсоемкое, но лучшее сжатие |
Delta | Целочисленные данные (ID, временные метки) | Хранит разницу между последовательными значениями |
Gorilla | Числа с плавающей запятой | Эффективное хранение сенсорных данных, значений временных рядов |
T64 | Малоценные целочисленные значения | Оптимизирован для повторяющихся целых чисел |
✅ Сжатые данные требуют меньшего числа чтений с диска
✅ Меньше использования места для больших наборов данных
7. Векторизованное выполнение (SIMD-оптимизированные запросы)
MergeTree обрабатывает данные пакетами (векторами) вместо построчной обработки:
- Использует SIMD (Single Instruction, Multiple Data), чтобы обрабатывать несколько значений за один цикл процессора.
- Оптимизировано для быстрых агрегаций.
✅ Колоссальное ускорение аналитических запросов
✅ Запросы типа SUM()
, AVG()
, COUNT()
выполняются гораздо быстрее
8. Рабочий процесс оптимизации выполнения запросов
1️⃣ Запрос анализируется.
2️⃣ Поиск разреженного индекса определяет релевантные гранулы.
3️⃣ Обрезка партиций пропускает ненужные партиции.
4️⃣ Векторизованное выполнение ускоряет вычисления.
9. Резюме: Почему MergeTree быстрый
✅ Столбцовое хранение снижает I/O
✅ Сортировка по первичному ключу ускоряет запросы по диапазону
✅ Разреженные индексы минимизируют нагрузку на память
✅ Партиционирование обрезает нерелевантные данные
✅ Фоновое слияние поддерживает оптимальное хранение данных
✅ Сжатие снижает объем данных и ускоряет чтение
✅ Векторизованное выполнение ускоряет агрегации