Словарь
Словарь в ClickHouse представляет собой хранимое в памяти ключ-значение представление данных из различных внутренних и внешних источников, оптимизированное для запросов с супер-низкой задержкой.
Словари полезны для:
- Повышения производительности запросов, особенно при использовании с
JOIN
s - Обогащения поступающих данных на лету без замедления процесса поступления

Ускорение соединений с использованием словаря
Словари могут использоваться для ускорения конкретного типа JOIN
: LEFT ANY
типа, где ключ соединения должен соответствовать атрибуту ключа базового хранилища ключ-значение.

Если это так, ClickHouse может использовать словарь для выполнения Прямого Соединения. Это самый быстрый алгоритм соединения ClickHouse и применяется, когда базовый движок таблицы для правой стороны таблицы поддерживает запросы ключ-значение с низкой задержкой. В ClickHouse есть три движка таблиц, предоставляющие эту возможность: Join (который по сути является предрассчитанной хеш-таблицей), EmbeddedRocksDB и Dictionary. Мы опишем подход, основанный на словаре, но механика одинакова для всех трех движков.
Алгоритм прямого соединения требует, чтобы правая таблица была поддержана словарем, таким образом, данные, которые будут объединены из этой таблицы, уже находятся в памяти в виде структуры данных ключ-значение с низкой задержкой.
Пример
Используя набор данных Stack Overflow, давайте ответим на вопрос: Какой пост вызывающий наибольшие споры относительно SQL на Hacker News?
Мы определяем спорный пост как пост, у которого примерно равное количество голосов «за» и «против». Мы вычисляем эту абсолютную разницу, где значение, ближе к 0, означает большее количество споров. Будем считать, что пост должен иметь не менее 10 голосов «за» и «против» - посты, за которые люди не голосуют, не очень спорные.
С нашими нормализованными данными, этот запрос в настоящее время требует JOIN
с таблицами posts
и votes
:
Используйте меньшие наборы данных с правой стороны
JOIN
: Этот запрос может показаться более многословным, чем требуется, с фильтрацией поPostId
как в внешнем, так и в подзапросах. Это оптимизация производительности, которая обеспечивает быстрое время отклика на запрос. Для оптимальной производительности всегда удостоверяйтесь, что правая сторонаJOIN
является меньшим набором и как можно меньшим. Для получения советов по оптимизации производительностиJOIN
и понимания доступных алгоритмов, мы рекомендуем эту серию статей в блоге.
Хотя этот запрос быстр, он зависит от того, что мы внимательно напишем JOIN
, чтобы добиться хорошей производительности. В идеале, мы просто отфильтровали бы посты так, чтобы в них содержалось "SQL", прежде чем смотреть на количество UpVote
и DownVote
для выбранного подмножества блогов для вычисления нашей метрики.
Применение словаря
Чтобы продемонстрировать эти концепции, мы используем словарь для наших данных о голосовании. Поскольку словари обычно хранятся в памяти (ssd_cache является исключением), пользователи должны быть осведомлены о размере данных. Подтверждаем размер нашей таблицы votes
:
Данные будут храниться несжатыми в нашем словаре, поэтому нам нужно как минимум 4 ГБ памяти, если мы хотим хранить все колонки (что не так). Словарь будет реплицироваться по кластерам, поэтому это количество памяти должно быть зарезервировано для каждого узла.
В примере ниже данные для нашего словаря получены из таблицы ClickHouse. В то время как это представляет собой самый распространенный источник словарей, поддерживается ряд источников, включая файлы, http и базы данных, включая Postgres. Как мы покажем, словари могут быть автоматически обновляемыми, что обеспечивает идеальный способ гарантировать, что маленькие наборы данных, подлежащие частым изменениям, доступны для прямых соединений.
Наш словарь требует первичного ключа, по которому будут выполняться поиска. Это концептуально идентично первичному ключу транзакционной базы данных и должно быть уникальным. Наш вышеуказанный запрос требует поиск по ключу соединения - PostId
. Словарь, в свою очередь, должен быть заполнен общим количеством голосов «за» и «против» для каждого PostId
из нашей таблицы votes
. Вот запрос для получения этих данных словаря:
Чтобы создать наш словарь, требуется следующий DDL - обратите внимание на использование нашего вышеуказанного запроса:
В самоуправляемом OSS вышеуказанная команда должна быть выполнена на всех узлах. В ClickHouse Cloud словарь будет автоматически реплицироваться на все узлы. Вышеуказанное было выполнено на узле ClickHouse Cloud с 64 ГБ ОЗУ, время загрузки составило 36 секунд.
Чтобы подтвердить использование памяти нашим словарем:
Теперь получить количество голосов «за» и «против» для конкретного PostId
можно с помощью простой функции dictGet
. Ниже мы получаем значения для поста 11227902
:
Этот запрос не только намного проще, но и более чем в два раза быстрее! Это можно было бы оптимизировать еще больше, загружая в словарь только посты с более чем 10 голосами «за» и «против» и храня только предрассчитанное спорное значение.
Обогащение данных во время запроса
Словари могут использоваться для поиска значений во время запроса. Эти значения могут возвращаться в результатах или использоваться в агрегациях. Предположим, мы создаем словарь для сопоставления идентификаторов пользователей с их местоположением:
Мы можем использовать этот словарь, чтобы обогатить результаты постов:
Подобно нашему предыдущему примеру соединения, мы можем использовать тот же словарь, чтобы эффективно определить, откуда происходят большинство постов:
Обогащение данных во время индексации
В приведенном выше примере мы использовали словарь во время запроса, чтобы убрать соединение. Словари также могут использоваться для обогащения строк во время вставки. Это обычно уместно, если значение обогащения не изменяется и существует во внешнем источнике, который можно использовать для заполнения словаря. В этом случае обогащение строки во время вставки избегает поиска в словаре во время запроса.
Предположим, что Location
пользователя в Stack Overflow никогда не меняется (на самом деле они меняются) - в частности, колонка Location
таблицы users
. Предположим, мы хотим сделать аналитический запрос к таблице постов по местоположению. Это содержит UserId
.
Словарь предоставляет сопоставление от идентификатора пользователя к местоположению, поддерживаемое таблицей users
:
Мы пропускаем пользователей с
Id < 0
, что позволяет нам использовать тип словаряHashed
. Пользователи сId < 0
являются системными пользователями.
Чтобы использовать этот словарь во время вставки для таблицы постов, нам нужно изменить схему:
В приведенном выше примере Location
объявляется как MATERIALIZED
колонка. Это означает, что значение может быть предоставлено как часть запроса INSERT
и всегда будет вычислено.
ClickHouse также поддерживает
DEFAULT
колонки (где значение может быть вставлено или вычислено, если не предоставлено).
Чтобы заполнить таблицу, мы можем использовать обычный INSERT INTO SELECT
из S3:
Теперь мы можем получить название местоположения, из которого происходит большинство постов:
Расширенные темы словаря
Выбор LAYOUT
словаря
Клаузула LAYOUT
управляет внутренней структурой данных для словаря. Существует несколько вариантов, которые описаны здесь. Некоторые советы по выбору правильного макета можно найти здесь.
Обновление словарей
Мы указали LIFETIME
для словаря MIN 600 MAX 900
. LIFETIME
- это интервал обновления для словаря, значения которого приводят к периодической перезагрузке в случайном интервале от 600 до 900 секунд. Этот случайный интервал необходим для распределения нагрузки на источник словаря при обновлении на большом количестве серверов. Во время обновлений старая версия словаря может по-прежнему запрашиваться, при этом только начальная загрузка блокирует запросы. Обратите внимание, что установка (LIFETIME(0))
предотвращает обновление словарей.
Словари можно принудительно перезагружать с помощью команды SYSTEM RELOAD DICTIONARY
.
Для источников данных, таких как ClickHouse и Postgres, вы можете настроить запрос, который будет обновлять словари только в том случае, если они действительно изменились (ответ на запрос это определяет), а не через периодический интервал. Подробности можно найти здесь.
Другие типы словарей
ClickHouse также поддерживает Иерархические, Полигональные и Словари регулярных выражений.