Перейти к основному содержимому
Перейти к основному содержимому

Словарь

Словарь в ClickHouse предоставляет представление данных в памяти в формате ключ-значение из различных внутренних и внешних источников, оптимизируя запросы для поиска с супернизкой задержкой.

Словари полезны для:

  • Улучшения производительности запросов, особенно при использовании с JOINs
  • Обогащения поступающих данных на лету, не замедляя процесс их поступления

Ускорение соединений с помощью словаря

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

Если это так, ClickHouse может использовать словарь для выполнения Прямого Соединения. Это самый быстрый алгоритм соединения ClickHouse и применим, когда основной движок таблиц для таблицы справа поддерживает запросы ключ-значение с низкой задержкой. В ClickHouse есть три движка таблиц, предлагающих эту возможность: Join (это по сути предварительно рассчитанная хеш-таблица), EmbeddedRocksDB и Dictionary. Мы опишем подход на основе словаря, но механика одинаковая для всех трех движков.

Алгоритм прямого соединения требует, чтобы правая таблица была поддержана словарем, таким образом, данные, которые будут соединяться из этой таблицы, уже находятся в памяти в форме структуры данных с низкой задержкой ключ-значение.

Пример

Используя набор данных Stack Overflow, давайте ответим на вопрос: Какой самый противоречивый пост по SQL на Hacker News?

Мы определим противоречивость как ситуацию, когда посты имеют похожее количество голосов "за" и "против". Мы вычисляем это абсолютное различие, где значение, ближе к 0, означает большую противоречивость. Мы предположим, что пост должен иметь как минимум 10 голосов "за" и "против" - посты, за которые не голосуют, не являются очень противоречивыми.

С нашими нормализованными данными, этот запрос в настоящее время требует JOIN с таблицами posts и votes:

Используйте меньшие наборы данных на правой стороне JOIN: Этот запрос может показаться более многословным, чем нужно, поскольку фильтрация по PostIds происходит как в внешнем, так и в подзапросах. Это оптимизация производительности, которая обеспечивает быстрое время отклика запроса. Для оптимальной производительности всегда убедитесь, что правая сторона 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 также поддерживает Иерархические, Полигональные и Словари регулярных выражений.

Дополнительные материалы