join_algorithm
Указывает, какой алгоритм JOIN используется. Можно указать несколько алгоритмов; для конкретного запроса будет выбран доступный вариант в зависимости от kind/strictness и движка таблицы. Будет ли алгоритм на основе hash сбрасывать данные на диск, этим выбором не определяется:max_bytes_before_external_join / max_bytes_ratio_before_external_join служат порогом сброса для всех из них (а как только одно из этих двух значений становится ненулевым, enable_adaptive_memory_spill_scheduler может сбросить JOIN на диск ещё раньше, при нехватке памяти), а max_rows_in_join / max_bytes_in_join — жёстким ограничением для всех из них, если только legacy_join_size_limits_trigger_spilling не превращает эти два ограничения обратно в триггеры сброса данных на диск. Выбранное значение определяет, как именно JOIN сбрасывает данные: grace_hash разбивает правую таблицу на партиции начиная с первого блока, а hash и parallel_hash собирают её в памяти и переключаются после превышения порога.
Большинство алгоритмов влияют на запрос только тогда, когда именно они выбраны для его выполнения. Однако некоторые изменяют планирование уже при самом наличии в списке — даже как резервный вариант с более низким приоритетом, который в итоге не выбирается, — поскольку решение принимается до выбора алгоритма. Есть два таких эффекта:
- Вывод типов ключей JOIN становится строже (например, соединение слиянием не может соединять ключи разных типов, такие как
StringиNullable(String)). Это может изменить типы результатов столбцовUSINGи привести к сбою JOIN с таблицей движкаJoinс ошибкойTYPE_MISMATCH. Срабатывает дляfull_sorting_mergeиparallel_full_sorting_merge. ORDER BY ... LIMITна сохраняемой стороне JOIN получает явную сортировку вместо чтения в порядке primary key, поскольку предполагается, что JOIN нарушает упорядоченное чтение (соединение слиянием вставляет собственную сортировку перед JOIN; частичное соединение слиянием повторно сортирует левые блоки; JOIN, который может создавать отложенные блоки, также не передаёт упорядоченное чтение). Результат тот же, но план менее эффективен. Срабатывает дляfull_sorting_merge,parallel_full_sorting_merge,partial_merge,prefer_partial_merge,grace_hashиauto, а также при ненулевом значенииmax_bytes_before_external_join/max_bytes_ratio_before_external_join.
hash или другим алгоритмом. Если это нежелательно, не указывайте перечисленные выше алгоритмы в join_algorithm для затронутых запросов.
Возможные значения:
- grace_hash
grace_hash является внешним начиная с первого блока: правая таблица сразу разбивается на партиции, тогда как hash и parallel_hash сначала собирают её в памяти и разбивают на партиции только после превышения порога сброса. Выбирайте его, когда заранее известно, что правая сторона не поместится в память, и хочется пропустить фазу работы в памяти. Сам порог сброса — тот же, что используют все алгоритмы на основе hash: max_bytes_before_external_join / max_bytes_ratio_before_external_join, и одно из этих двух значений должно быть ненулевым, если только не включён legacy_join_size_limits_trigger_spilling. Без порога grace_hash пропускается в пользу следующего алгоритма из списка, а если он единственный — отклоняется.
На первом этапе grace join читается правая таблица, и она разбивается на N бакетов в зависимости от значения hash ключевых столбцов (изначально N равно grace_hash_join_initial_buckets). Это делается так, чтобы каждый бакет мог обрабатываться независимо. Строки из первого бакета добавляются в hash table в памяти, а остальные сохраняются на диск. Если hash table вырастает сверх порога сброса, число бакетов увеличивается вместе с назначенным бакетом для каждой строки. Все строки, которые не принадлежат текущему бакету, сбрасываются и переназначаются.
Поддерживает INNER/LEFT/RIGHT/FULL ALL/ANY JOIN.
- hash
OR в секции JOIN ON.
При использовании алгоритма hash правая часть JOIN загружается в оперативную память.
- parallel_hash
hash join, которая разбивает данные на бакеты и строит несколько hash-таблиц вместо одной параллельно, чтобы ускорить этот процесс.
При использовании алгоритма parallel_hash правая часть JOIN загружается в оперативную память.
- partial_merge
RIGHT JOIN и FULL JOIN поддерживаются только со strictness ALL (SEMI, ANTI, ANY и ASOF не поддерживаются).
При использовании алгоритма partial_merge ClickHouse сортирует данные и сбрасывает их на диск. Алгоритм partial_merge в ClickHouse немного отличается от классической реализации. Сначала ClickHouse сортирует правую таблицу по ключам JOIN блоками и создаёт min-max индекс для отсортированных блоков. Затем он сортирует части левой таблицы по join key и соединяет их с правой таблицей. Min-max индекс также используется для пропуска ненужных блоков правой таблицы.
- direct
direct (также известный как nested loop) выполняет lookup в правой таблице, используя строки из левой таблицы в качестве ключей.
Он поддерживается специальными хранилищами, такими как Dictionary, EmbeddedRocksDB и таблицами MergeTree.
Для таблиц MergeTree алгоритм передаёт фильтры по ключу JOIN напрямую на уровень хранения. Это может быть эффективнее, если ключ позволяет использовать primary key index таблицы для lookup; в противном случае для каждого блока левой таблицы выполняется полное сканирование правой таблицы.
Поддерживает INNER и LEFT joins и только одностолбцовые ключи JOIN по равенству без дополнительных условий.
- auto
auto, сначала пробуется hash JOIN, а затем алгоритм на лету переключается на другой, если превышается memory limit.
- full_sorting_merge
- ie_join
JOIN, в секции ON которого есть два сравнения на неравенство (<, <=, >, >=) между выражениями соединяемых таблиц. Поддерживает ALL INNER/LEFT/RIGHT/FULL JOIN и SEMI/ANTI LEFT/RIGHT JOIN.
Позиция в списке задаёт приоритет: если IEJoin указан после других алгоритмов, он используется только когда они неприменимы (в секции ON нет условий равенства); если указан первым, он используется всегда, когда секция ON содержит два условия неравенства. Остальные условия (включая равенства) применяются как фильтр к результату JOIN для ALL INNER JOIN, а для остальных видов вычисляются внутри оператора как остаточное условие, влияющее на сопоставление. Когда секция ON содержит более двух подходящих условий неравенства, два условия, используемые алгоритмом, выбираются по их оценочной селективности на основе min/max статистики столбцов (см. тип basic в разделе Статистика столбцов); если оценки недоступны (нет статистики или отключена use_statistics), используются первые два условия в синтаксическом порядке. Без ie_join в списке INNER JOIN, содержащий только условия неравенства, выполняется как CROSS JOIN с фильтром, а остальные виды не поддерживаются.
Оба входных набора данных накапливаются в памяти перед JOIN: max_rows_in_join и max_bytes_in_join ограничивают суммарный объём накопленных входных данных с обеих сторон (а не только с правой), а действие при переполнении задаётся параметром join_overflow_mode; индексы сортировки, которые оператор строит для накопленных входных данных, не учитываются при подсчёте лимита. Сам оператор JOIN работает в одном потоке; распараллеливаются только сортировки входных данных перед JOIN.
- parallel_full_sorting_merge
full_sorting_merge, но JOIN по равенству, совместимые с hash, разбиваются на сегменты по hash ключей JOIN, образуя независимые соединения слиянием для каждого сегмента, которые выполняются параллельно (до max_threads), вместо одного соединения слиянием. Это сохраняет низкое потребление памяти при потоковой обработке, характерное для соединения слиянием, при этом задействуются все потоки, а результат не упорядочен.
Hash-сегментирование по ключам JOIN применяется только к простым JOIN по равенству для типов ключей, hash которых согласован со сравнением соединения слиянием, и только если ни одна из сторон ещё не отсортирована. Оно пропускается в следующих случаях:
- JOIN
ASOFи типы ключей floating-point /JSON/Object/Dynamic: их hash несовместимы со сравнением соединения слиянием, поэтому равные ключи могут попасть в разные сегменты. - Стороны, которые уже отсортированы (чтение MergeTree по порядку или любые предварительно отсортированные входные данные): сохраняющее порядок распределение по соединениям слиянием для каждого сегмента может привести к взаимной блокировке конвейера. Вместо этого сохраняются чтение по порядку и его оптимизация
read_in_order_use_virtual_row. - Когда инициатор строит распределённый план (
make_distributed_plan), поскольку распределённая сортировка не сериализуема для удалённого выполнения. Локальный односегментный план и фрагменты для каждого worker повторно оптимизируются с отключённой этой настройкой, поэтому всё ещё могут быть сегментированы.
full_sorting_merge, а стороны MergeTree, читаемые по порядку, всё ещё могут сегментироваться на уровне источника по диапазонам primary key (которые упорядочены тем же сравнением, что используется в JOIN, поэтому равные ключи остаются вместе), когда включён query_plan_join_shard_by_pk_ranges.
- prefer_partial_merge
partial_merge, если это возможно, иначе использует hash. Устарело, то же, что partial_merge,hash.
- default (устарело)
direct,hash, то есть сначала попробуйте использовать direct JOIN, затем hash JOIN (в таком порядке).
join_any_take_last_row
Изменяет поведение операций JOIN со strictnessANY, когда в правой таблице для ключа есть более одной совпадающей строки.
Этот параметр применяется к таблицам с движком
Join и алгоритмам JOIN на основе хеша.Если JOIN строится параллельно, порядок строк может быть недетерминированным. Это означает, что join_any_take_last_row = 1 может возвращать недетерминированную строку для запросов ANY JOIN.- 0 — Если в правой таблице есть более одной совпадающей строки, присоединяется только первая найденная.
- 1 — Если в правой таблице есть более одной совпадающей строки, присоединяется только последняя найденная.
join_default_strictness
Задаёт strictness по умолчанию для секций JOIN. Возможные значения:ALL— Если в правой таблице есть несколько совпадающих строк, ClickHouse создаёт декартово произведение из совпадающих строк. Это обычное поведениеJOINв стандартном SQL.ANY— Если в правой таблице есть несколько совпадающих строк, присоединяется только первая найденная. Если в правой таблице есть только одна совпадающая строка, результатыANYиALLбудут одинаковыми.ASOF— Для соединения последовательностей с неточным совпадением.Empty string— Если в запросе не указаныALLилиANY, ClickHouse генерирует исключение.
join_on_disk_max_files_to_merge
Ограничивает количество файлов, используемых для параллельной сортировки в операциях MergeJoin при их выполнении на диске. Чем больше значение настройки, тем больше используется оперативной памяти и тем меньше требуется дисковых операций ввода-вывода. Возможные значения:- Любое положительное целое число, начиная с 2.
join_output_by_rowlist_perkey_rows_threshold
Нижний порог среднего числа строк на ключ в правой таблице, определяющий, следует ли использовать вывод по списку строк при hash JOIN.join_overflow_mode
Определяет, какое действие выполняет ClickHouse, когда при JOIN достигается одно из следующих ограничений: Этот параметр учитывается всеми значениямиjoin_algorithm,
основанными на хеше, включая те, что сбрасывают данные на диск: достижение
ограничения останавливает запрос, а не приводит к сбросу данных на диск. Исключением является
legacy_join_size_limits_trigger_spilling: когда он включён, та часть JOIN, которая
уже выполняется на диске, продолжает сбрасывать данные на диск вместо применения этого параметра.
ie_join также учитывает его — для входных данных, накапливаемых с обеих сторон. partial_merge по-прежнему
обрабатывает эти ограничения переключением стратегии — см.
join_algorithm.
Возможные значения:
THROW— ClickHouse генерирует исключение и останавливает запрос.BREAK— ClickHouse останавливает запрос и не генерирует исключение.
THROW.
См. также