JOIN и широкий выбор алгоритмов JOIN. Чтобы добиться максимальной производительности, рекомендуем следовать советам по оптимизации JOIN из этого руководства.
- Для оптимальной производительности следует стремиться уменьшить количество
JOINв запросах, особенно для аналитических рабочих нагрузок в реальном времени, где важна задержка на уровне миллисекунд. Старайтесь, чтобы в одном запросе было не более 3–4 JOIN. В разделе о моделировании данных мы подробно рассматриваем несколько способов минимизировать количество JOIN, включая денормализацию, словари и материализованные представления. - Начиная с ClickHouse 24.12, планировщик запросов автоматически переставляет JOIN двух таблиц так, чтобы меньшая таблица находилась справа для оптимальной производительности. В версии 25.9 эта возможность была расширена и теперь оптимизирует порядок JOIN в запросах с тремя и более таблицами.
- Если вашему запросу нужен прямой JOIN, то есть
LEFT ANY JOIN, как показано ниже, мы рекомендуем по возможности использовать Dictionaries.
- При выполнении inner JOIN часто эффективнее записывать их как подзапросы с использованием предложения
IN. Рассмотрим следующие запросы, которые функционально эквивалентны. Оба находят количествоposts, где ClickHouse не упоминается в вопросе, но упоминается вcomments.
ANY INNER JOIN, а не просто INNER JOIN, поскольку нам не нужно декартово произведение, то есть для каждого поста нам нужно только одно совпадение.
Этот JOIN можно переписать с помощью подзапроса, что значительно улучшит производительность:
JOIN. Рассмотрим пример, где нужно вычислить количество положительных голосов за посты, связанные с Java, начиная с 2020 года.
Наивный запрос, в котором более крупная таблица находится слева, выполняется за 56 с:
INNER JOIN в подзапрос, как отмечалось ранее, и сохранив фильтр и во внешнем, и во внутреннем запросе.
Выбор алгоритма JOIN
Эти алгоритмы определяют, как запрос с JOIN планируется и выполняется. По умолчанию ClickHouse использует алгоритм direct или hash join в зависимости от типа JOIN, strictness и движка соединяемых таблиц. Кроме того, ClickHouse можно настроить на адаптивный выбор и динамическую смену алгоритма JOIN во время выполнения в зависимости от доступности и использования ресурсов: когда
join_algorithm=auto, ClickHouse сначала пробует алгоритм hash join, а если превышается лимит памяти для этого алгоритма, на лету переключается на частичное соединение слиянием. Определить, какой алгоритм был выбран, можно с помощью trace logging. ClickHouse также позволяет явно указать нужный алгоритм JOIN через настройку join_algorithm.
Поддерживаемые типы JOIN для каждого алгоритма JOIN показаны ниже; их следует учитывать перед оптимизацией:
Полное подробное описание каждого алгоритма
JOIN, включая их преимущества, недостатки и свойства масштабирования, можно найти здесь.
Выбор подходящего алгоритма JOIN зависит от того, что вы хотите оптимизировать: использование памяти или производительность.
Оптимизация производительности JOIN
-
(1) Если данные из правой таблицы можно заранее загрузить в размещённую в памяти низколатентную структуру данных ключ-значение, например в словарь, если ключ JOIN совпадает с ключевым атрибутом базового хранилища ключ-значение и если семантики
LEFT ANY JOINдостаточно, то можно использовать direct JOIN — это самый быстрый вариант. - (2) Если физический порядок строк в таблице совпадает с порядком сортировки ключа JOIN, то всё зависит от ситуации. В этом случае полное сортирующее соединение слиянием пропускает фазу сортировки, что значительно снижает использование памяти и, в зависимости от объёма данных и распределения значений в столбцах ключа JOIN, может выполняться быстрее, чем некоторые алгоритмы hash JOIN.
- (3) Если правая таблица помещается в память даже с учётом дополнительных накладных расходов на использование памяти у параллельного hash JOIN, то этот алгоритм или hash JOIN может оказаться быстрее. Это зависит от объёма данных, типов данных и распределения значений в столбцах ключа JOIN.
- (4) Если правая таблица не помещается в память, то здесь снова всё зависит от ситуации. ClickHouse предлагает три алгоритма JOIN, не ограниченных объёмом памяти. Все три временно выполняют сброс данных на диск. Полное сортирующее соединение слиянием и частичное соединение слиянием требуют предварительной сортировки данных. Grace hash JOIN вместо этого строит hash-таблицы из данных. В зависимости от объёма данных, типов данных и распределения значений в столбцах ключа JOIN в некоторых сценариях построение hash-таблиц может быть быстрее сортировки данных. И наоборот.
Оптимизация использования памяти
- (1) Если физический порядок строк в таблице соответствует порядку сортировки ключа JOIN, то полное сортирующее соединение слиянием обеспечивает минимально возможное использование памяти. Дополнительное преимущество — высокая скорость JOIN, поскольку этап сортировки отключён.
- (2) grace hash join можно настроить на очень низкое использование памяти, задав большое количество бакетов ценой скорости JOIN. частичное соединение слиянием намеренно использует небольшой объём оперативной памяти. полное сортирующее соединение слиянием с включённой внешней сортировкой обычно использует больше памяти, чем частичное соединение слиянием (если порядок строк не соответствует порядку сортировки ключа), но обеспечивает значительно меньшее время выполнения JOIN.