Введение
ClickHouse — это столбчатая база данных для онлайн-анализа (OLAP), разработанная и размещенная в открытом доступе российской поисковой компанией.
Ключевые особенности сценариев OLAP
- В основном прочитанные запросы
- Запись данных большими партиями (> 1000 строк)
- Не изменять добавленные данные
- Каждый запрос считывает большое количество строк из базы данных, но только небольшое количество столбцов.
- Широкие таблицы, каждая с большим количеством столбцов
- Меньше запросов
- Нужно много дел
- Низкие требования к согласованности данных
- но высокая пропускная способность запросов (до миллиардов строк в секунду на сервер)
- Каждый запрос небольшой, за исключением одной большой таблицы
- Результат запроса значительно меньше исходных данных
Архитектура
Основные особенности
Полная функция СУБД
Описывает данные с помощью реляционной модели и обеспечивает основные функции традиционной базы данных.
Поддержка DDL, DML, контроль разрешений, резервное копирование и восстановление данных, распределенное управление
Столбчатое хранилище и сжатие данных
Чтобы запросы выполнялись быстрее, вы можете уменьшить диапазон сканирования данных и объем передаваемых данных.
ClickHouse использует столбчатую структуру хранения,
Для пользовательской таблицы будет много автоматики, но когда запрашиваются только 2 поляselect id,name from user
, MySQL сканирует всю таблицу, в то время как для столбцового хранилища считываются только эти два столбца данных, что эффективно уменьшает диапазон сканирования данных и повышает эффективность ввода-вывода.
Суть алгоритма сжатия заключается в кодировании и преобразовании повторяющихся данных для уменьшения длины данных, ClickHouse по умолчанию использует алгоритм сжатия LZ4.
Векторизованный исполнительный движок
Векторизованное выполнение требует использования инструкции ЦП SIMD (Single Instruction Multiple Data).Одна инструкция работает с несколькими фрагментами данных.Одним из способов повышения производительности за счет параллелизма данных является реализация параллельных операций с данными на уровне регистров ЦП.
Разнообразные настольные двигатели
объединить дерево | журнал | интегрированный | очень |
---|---|---|---|
MergeTree | Tinylog | Kafka | Distributed |
SummingMergeTree | StripeLog | Mysql | Dictionary |
AggregatingMergeTree | Log | JDBC | Merge |
CollapsingMergeTree | ODBC | File | |
VersionCollapsingMergeTree | HDFS | Set | |
GragphieMergeTree | Join | ||
URL | |||
View | |||
MaterializedView | |||
Memory | |||
Buffer |
Распределенный и многопоточный
向量化执行通过数据级并行的方式提升性能
多线程处理通过线程级并行的方式提升性能
Поддержка разделов — масштабируйте, используйте преимущества многопоточности
Поддержка сегментирования — горизонтального расширения с использованием распределенных принципов.
Многоуровневая архитектура
Multi-Master multi-master архитектура, роли каждого узла в кластере равны, и клиент может получить одинаковый эффект при доступе к любому узлу.
Механизм таблицы журналов
Лог используется для быстрого чтения и записи небольших таблиц (1 млн строк), а затем чтения их всех
- Разделение и индексация не поддерживаются
- Удаление и обновление не поддерживаются
- последовательность данных добавить диск
- Атомарная запись не поддерживается
- вставка заблокирует выбор
Сортировать по производительности:
- tinylog: самая низкая производительность, не поддерживает параллельное чтение, плохая производительность запросов, подходит для временного хранения промежуточных данных
- Striplog: поддерживает одновременное чтение, все столбцы хранятся в одном файле
- log: поддерживает одновременное чтение, каждый столбец хранит отдельный файл
специальный настольный двигатель
memory
С типом таблицы памяти mysql данные сохраняются в памяти, и данные будут потеряны после перезапуска.
buffer
Если указанные условия соблюдены, он будет сброшен на диск
Buffer(database, table, num_layers, min_time, max_time, min_rows, max_rows, min_bytes, max_bytes)
create table test.buffer_to_memory_1 as test.memory_1 engine = Buffer(test, memory_1, 16, 10 ,100, 1000, 1000000, 10000000, 100000000);
Данные, вставленные в буферную таблицу, могут быть записаны в целевую таблицу в другом порядке и в разных блоках.
Удовлетворить все min_, или любой max_ сбросит данные в таблицу memory_1
file
прямо в файле
движок таблицы дерева слияния
MergeTree
- Раздел поддержки
- Хранится в порядке
- индекс первичного ключа
- данные ttl
- разреженный индекс
主键数据可以重复
create table test_1( id UInt16, create_time Date )ENGINE=MergeTree() PARTITION BY toYYYYMMDD(create_time) ORDER BY (id,create_time) PRIMARY KEY (id,create_time) TTL create_time + INTERVAL 1 MONTH
PRIMARY KEY
Если не определено, используйте поле ORDER BY в качестве первичного ключа.
toYYYYMMDD(create_time)
Разделить данные по дням
TTL create_time + INTERVAL 1 MONTH
Данные хранятся в течение одного месяца
ReplacingMergeTree
чтобы решитьMergeTree
Проблема в том, что один и тот же первичный ключ не может быть дедуплицирован, вводится ReplacingMergeTree
но и принуждениеoptimize
optimize table test_re
существующие проблемы
- оптимизация - это фоновое действие, которое не может удовлетворить потребности своевременного бизнес-запроса.
- При шардинге данные находятся в разных шардах, и функцию дедупликации реализовать невозможно
Больше используется для обеспечения того, чтобы данные в конечном итоге были дедуплицированы.
CollapingMergeTree
Дальнейшее улучшение ReplacingMergeTree, добавление поля Sign
create table test_2( id UInt16, ViewNum UInt16, create_time Date, Sign Int8 )ENGINE=CollapingMergeTree(Sign) GROUP BY ID;
Данные Sign=1 действительны, данные Sign=-1 удалены
Новые данные: ВСТАВИТЬ В ТЕСТ_2(...,1)
Удалить данные: INSERT INTO TEST_2(...,-1)
В случае многопоточной записи запись -1 записывается первой, что вызовет нормальное сворачивание
нужно переписатьsql
SELECT id,sum(ViewNum * Sign) FROM test_2 GROUP BY id HAVING sum(Sign)>0;
VersionedCollapsingMergeTree
Чтобы решить проблему, заключающуюся в том, что запись CollapingMergeTree не по порядку не может быть правильно свернута
Добавить новый столбец номера версии
Строки с одним и тем же первичным ключом, одной и той же версией и противоположным знаком будут удалены во время сжатия.
create table test_3( id UInt16, ViewNum UInt16, create_time Date, Sign Int8, Version UInt8 )ENGINE=VersionedCollapsingMergeTree(Sign,Version) GROUP BY ID;
тоже надо переписатьsql
SELECT id,sum(ViewNum * Sign) FROM test_3 GROUP BY id HAVING sum(Sign)>0;
SummingMergeTree
Столбец первичного ключа может быть предварительно агрегирован, и при объединении в фоновом режиме будут суммироваться строки с одинаковым первичным ключом.
Уменьшите дисковое пространство и ускорьте запрос данных
- Данные будут агрегироваться только при объединении в фоновом режиме, поэтому для запроса sql по-прежнему требуется GROUP BY
- Во время предварительной агрегации сумма будет выполняться по столбцам, кроме первичного ключа. Если столбец не является числовым, значение в строке будет выбрано случайным образом.
AggregatingMergeTree
Это также своего рода механизм предварительной агрегации.
SummingMergeTree выполняет суммирование по столбцам, не являющимся первичными ключами.
AggregatingMergeTree может указывать различные функции агрегации.
Использование с материализованными представлениями
-- 创建明细表
CREATE TABLE test.visits(
UserID UInt64,
CounterID UInt8,
StartDate Date,
Sign Int8
)ENGINE CollapsingMergeTree(Sign)
ORDER BY UserID;
-- 创建物化视图
CREATE MATERIALIZED VIEW test.basic
ENGINE = AggregatingMergeTree()
PARTITION BY toYYYYMM(StartDate)
ORDER BY (CounterID, StartDate)
AS SELECT
CounterID,
StartDate,
sumState(Sign) AS Visits,
uniqState(UserID) AS Users
FROM test.visits GROUP BY CounterID, StartDate;
-- 插入数据到明显表中
INSERT INTO test.visits VALUES (1, 1, '2020-08-11', 1), (2, 11, '2020-08-11', 1), (3, 12, '2020-08-11', 1);
-- 查询物化视图
SELECT
StartDate,
sumMerge(Visits) as Visits,
uniqMerge(Users) as Users
FROM test.basic
GROUP BY StartDate
ORDER BY StartDate;