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