Уровень хранения: параллельные вставки изолированы друг от друга
Уровень хранения: одновременные вставки и SELECT-запросы изолированы
Уровень хранения: вычисления при слиянии
- Replacing merges сохраняют только самую свежую версию строки во входных частях и отбрасывают все остальные версии. Replacing merges можно рассматривать как операцию очистки при слиянии.
- Aggregating merges объединяют промежуточные состояния агрегации во входной части в новое состояние агрегации. Хотя это может звучать сложно, на практике это просто реализует инкрементальную агрегацию.
- TTL (time-to-live) merges сжимают, перемещают или удаляют строки на основе определённых правил, завязанных на времени.
Уровень хранения: отсечение данных
- Индексы первичного ключа, которые определяют порядок сортировки данных таблицы. Правильно выбранный первичный ключ позволяет применять фильтры (например, предложение WHERE в приведённом выше запросе) с помощью быстрого двоичного поиска вместо полного сканирования столбцов. Говоря более технически, время выполнения сканирования становится логарифмическим, а не линейным относительно объёма данных.
- Проекции таблиц — альтернативные внутренние версии таблицы, хранящие те же данные, но отсортированные по другому первичному ключу. Проекции могут быть полезны, когда часто используется несколько условий фильтрации.
- Индексы пропуска данных, которые сохраняют для столбцов дополнительную статистику, например минимальное и максимальное значение столбца, набор уникальных значений и т. д. Индексы пропуска данных дополняют первичные ключи и проекции таблиц и, в зависимости от распределения данных в столбце, могут значительно ускорить применение фильтров.
Уровень хранения: сжатие данных
Передовой уровень обработки запросов
Скрупулёзное внимание к деталям
“ClickHouse — это просто безумная система: у вас тут 20 версий хеш-таблицы. У вас есть все эти невероятные штуки, тогда как в большинстве систем будет одна хеш-таблица … у ClickHouse такая впечатляющая производительность именно потому, что в нём есть все эти специализированные компоненты” Andy Pavlo, профессор баз данных в CMUClickHouse выделяет именно скрупулёзное внимание к низкоуровневой оптимизации. Создать базу данных, которая просто работает, — это одно, но спроектировать её так, чтобы она обеспечивала высокую скорость для самых разных типов запросов, структур данных, распределений данных и конфигураций индексов, — вот где проявляется мастерство “безумной системы”. Хеш-таблицы. Возьмём в качестве примера хеш-таблицу. Хеш-таблицы — это ключевые структуры данных, лежащие в основе JOIN и агрегаций. С точки зрения программиста здесь нужно учитывать следующие проектные решения:
- Какую хеш-функцию выбрать,
- Как разрешать коллизии: открытая адресация или цепочки,
- Структура памяти: один массив для ключей и значений или отдельные массивы?
- Коэффициент заполнения: когда и как менять размер? Как перемещать значения при изменении размера?
- Удаление: должна ли хеш-таблица поддерживать вытеснение записей?
- Что будет сортироваться: числа, Tuple, строки или структуры?
- Находятся ли данные в оперативной памяти?
- Требуется ли стабильная сортировка?
- Нужно ли сортировать все данные или достаточно частичной сортировки?