Какие виды физических join существуют кроме broadcast join?
Что проверяют
Знаете ли вы, как движок на самом деле исполняет соединение, а не только какие бывают INNER и LEFT. Раз прозвучал broadcast, речь почти наверняка о Spark. Следом спрашивают, как узнать, какой join выбран, и что делать с перекосом ключей.
Как отвечать
Сначала разведите логический тип соединения (inner, left, semi, anti) и физическую стратегию: первый описывает результат, вторая способ его получить. В Spark SQL стратегий пять:
- Broadcast Hash Join: маленькая таблица рассылается на все executor, большая не перемешивается. Включается сам, если оценка размера меньше
spark.sql.autoBroadcastJoinThreshold, по умолчанию 10 МБ; - Sort Merge Join: обе стороны перемешиваются по ключу, сортируются и сливаются. Основная стратегия для двух больших таблиц при соединении по равенству;
- Shuffle Hash Join: перемешивание без сортировки, по меньшей стороне в каждой партиции строится хэш-таблица. Быстрее сортировки, но рискует упасть по памяти;
- Broadcast Nested Loop Join: для условий без равенства, например
a.ts BETWEEN b.start AND b.end, когда одну сторону можно разослать; - Cartesian Product: декартово произведение, крайний вариант.
Выбор виден в df.explain() и во вкладке SQL в Spark UI. Повлиять можно хинтами BROADCAST, MERGE, SHUFFLE_HASH, SHUFFLE_REPLICATE_NL. Adaptive Query Execution, включённый по умолчанию начиная со Spark 3.2, умеет на лету заменить Sort Merge Join на broadcast по реальному размеру данных и дробить перекошенные партиции.
Полезна параллель с классическими СУБД: там те же идеи называются Nested Loop, Hash Join и Merge Join и видны в EXPLAIN.
Где спотыкаются
Перечисляют inner, outer, cross и self join. Это логические типы, и на вопрос о физических такой ответ засчитывают как неверный.
Считают broadcast всегда выгодным и поднимают порог до гигабайтов. Таблица собирается на драйвере и копируется на каждый executor, это короткий путь к OutOfMemory.
Не думают о перекосе. Если на один ключ приходится половина строк, одна задача работает час, пока остальные простаивают; помогают skew join в AQE или соление ключа.