[Документация Yandex Cloud](../../../../index.md) > [Yandex DataLens](../../../index.md) > Подключения > Базы данных > Создание подключения к YTsaurus CHYT > Особенности JOIN

# Особенности JOIN в Yandex DataLens

В интерфейсе создания датасета можно [объединять данные](../../../dataset/create-dataset.md#links), перетаскивая таблицы на рабочую область и настраивая связи между ними через оператор `JOIN`. Для таблиц YTsaurus такое объединение вызывает ошибку. Ошибка возникает из-за структуры хранения таблиц и схемы выполнения запросов в YTsaurus по умолчанию. Чтобы избежать ошибки, используйте [SQL-запрос к источнику](../../../dataset/create-dataset.md#add-data).

## Хранение табличных данных {#table-data-storage}

Схема хранения таблиц в YTsaurus принципиально отличается от таковой в ClickHouse®:

* В YTsaurus базовый примитив хранения данных — статическая таблица, строки которой лежат по чанкам, произвольным образом распределенным по кластеру. По умолчанию данные распределяются по шардам согласно некоторому ключу шардирования. Статические таблицы крайне неэффективны в задачах, которые требуют точечного чтения данных.

  {% note info %}

  В ClickHouse® шардирование обеспечивает локальность строк с одним значением выражения шардирования на одной машине.

  {% endnote %}

* В YTsaurus поддерживается понятие сортированной таблицы — в схеме таблицы может учитываться, что ее строки сортированы по некоторому префиксу колонок. Такие колонки называются ключевыми. Это более эффективный примитив хранения данных — динамическая таблица.

  {% note info %}

  В YTsaurus сортировка обеспечивает локальность строк с одним значением ключа в одном чанке (либо в наборе подряд идущих).

  {% endnote %}

## Простой SELECT-запрос в CHYT {#sql-select-query}

SELECT-запрос, не содержащий оператора `JOIN`, по своей сути является потоковым. В нем происходит чтение данных из единственного источника и последующая обработка строк. Возможно применение к полям функций и агрегаций.

В CHYT такой запрос реализован следующим образом:

1. На некоторый инстанс клики поступает такой запрос. Данный инстанс называется координатором запроса, так как он определяет дальнейший план выполнения.
1. Координатор отправляет в каждый инстанс по внутреннему tcp-протоколу переписанный запрос. В этом запросе вместо названия входной таблицы подставлена закодированная последовательность `chunk slice`, где `chunk slice` это некоторый диапазон внутри одного чанка. (Диапазон задается граничными номерами строк или ключами.)
1. Каждый инстанс исполняет переписанный запрос, и возвращает координатору результат исполнения, тот производит финальную агрегацию (если нужно) и уже отвечает пользователю.

## Виды запросов с JOIN в ClickHouse® {#sql-join-query-ch}

Как и в случае с простым запросом, SELECT-запрос с использованием оператора `JOIN` поступает на инстанс клики, который называется координатором запроса. Координатор запроса определяет дальнейший план выполнения, а распределение нагрузки между инстансами определяется вариантом исполнения конструкции `lhs JOIN rhs USING/ON`:

* **Distributed local JOIN** выполняется в ClickHouse® по умолчанию. Если таблицы шардированы одинаковым образом, то совпадающая пара ключей не может оказаться на разных машинах. Таким образом, `lhs` и `rhs` на каждом инстансе интерпретируются как соответствующие им локальные таблицы. При этом разбитый координатором на части запрос можно исполнять независимо на каждом инстансе.

  {% note info %}

  Метод требует использование одинаковой схемы шардирования на таблицах.

  {% endnote %}

* **GLOBAL JOIN** выполняется, если использовать ключевое слово `GLOBAL` рядом с `JOIN`. На координаторе запроса полностью исполняется и материализуется правый аргумент `rhs`. Затем его сериализованное представление рассылается вместе с запросом по инстансам. Инстансы используют это представление для получения правой части в своей памяти. Подробнее в [документации](https://clickhouse.com/docs/ru/sql-reference/operators/in#select-distributed-subqueries).

  {% note info %}

  * Данный метод эффективен, когда `rhs` сравнительно небольшого размера, а инстансов сравнительно немного. Иначе может возникнуть нехватка ресурсов при выполнении `rhs` на координаторе, или при раздаче координатором по сети сериализованного представления с подзапросом.
  * Метод не требует никаких дополнительных условий на согласованность схемы хранения/шардирования на таблицах.

  {% endnote %}

* **JOIN via subqueries**. ClickHouse® позволяет заключить `lhs` и/или `rhs` в скобки, и это существенно влияет на план исполнения:

  {% list tabs %}

  - Окружить lhs в скобки

    1. На координаторе независимо исполняется левая часть.
    1. Независимо исполняется правая часть.
    1. Правая часть помещается в оперативную память в хеш-таблицу.
    1. Происходит полное исполнение `JOIN` только на координаторе.

  - Окружить rhs в скобки

    1. На координаторе независимо исполняется левая часть, как если бы запрос выглядел просто как SELECT `lhs`.
    1. Координатор отправляет на инстансы свои запросы, оставив `JOIN` (`rhs`) как есть.
    1. Каждый инстанс исполняет `rhs` независимо.

       {% note info %}

       Это может привести к кратно большей нагрузке, так как каждый инстанс будет материализовывать правую часть независимо. Поэтому защитный механизм в ClickHouse® по умолчанию запрещает такое поведение и приводит к ошибке `Double-distributed IN/JOIN subqueries is denied`.

       {% endnote %}

  {% endlist %}

## Особенность запросов с JOIN в CHYT {#sql-join-query-yt}

При выполнении SELECT-запроса с использованием оператора `JOIN` в CHYT по умолчанию действует логика **Sorted JOIN**. Она основана на одинаковой схеме сортировки колонок. Используется обычная конструкция `lhs JOIN rhs USING/ON`.

При этом на `lhs` и `rhs` налагаются дополнительные ограничения:

* Части `lhs` и `rhs` должны быть сортированными таблицами.
* В условии `USING/ON` должны использоваться только отсортированные колонки.

Например:

* Пусть `lhs` отсортирована по колонкам `l1, l2, ..., ln` , а `rhs` — по колонкам `r1, r2, ..., rm`.
* Условие `JOIN` `ON` должно выглядеть как набор равенств `l1 = r1 , ..., lk = rk` для некоторого `k` (сами равенства могут идти в произвольном порядке).
* Это может быть выражено как набором равенств в условии `ON`, так и набором общих ключевых колонок в конструкции `USING`, но не набором равенств в условии `WHERE`.

При соблюдении этих условий координатор запроса формирует пары соответствующих диапазонов из `lhs` и `rhs` и распределяет их по инстансам в подзапросах.

Если же это условие не выполнено, выходит ошибка. В этом случае следует либо использовать `GLOBAL JOIN`, либо заключать правую часть (`rhs`) в подзапрос.

_ClickHouse® является зарегистрированным товарным знаком [ClickHouse, Inc](https://clickhouse.com)._