Хеш-соединение, соединение слиянием и вложенный цикл
Познакомьтесь с тремя основными стратегиями соединения, их профилями стоимости и условиями, при которых планировщик выбирает каждую из них
«Хеш-соединение, соединение слиянием и вложенный цикл» — бесплатный урок SQL Academy на CoddyKit. Это урок 3 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения SQL Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс SQL Academy содержит 4 уроков всего.
Три стратегии соединения
PostgreSQL использует три физических алгоритма соединения:
- Вложенный цикл — для каждой внешней строки сканирует внутреннюю
- Хеш-соединение — строит хеш-таблицу по внутренней стороне и выполняет поиск по ней с внешней
- Соединение слиянием — обе стороны отсортированы и сливаются одновременно
Вложенный цикл
Простейший вариант: внешняя × внутренняя таблица. Быстро, когда у внутренней таблицы есть хороший индекс AND внешняя таблица мала:
EXPLAIN ANALYZE
SELECT * FROM users u JOIN orders o ON o.user_id = u.id
WHERE u.id = 42;
-- Nested Loop
-- -> Index Scan on users where id = 42 (rows=1)
-- -> Index Scan on orders_user_id_idx (rows=5)Когда вложенный цикл выигрывает
Во внешней части мало строк AND во внутренней есть индекс по ключу соединения — вложенный цикл чрезвычайно быстр. Худший случай: O(внешняя × внутренняя).
Хеш-соединение
Постройте хеш-таблицу по одной стороне (обычно меньшей), затем выполняйте поиск по ней с другой стороны. Отлично подходит для соединения двух больших таблиц, когда по ключу соединения нет полезного индекса:
EXPLAIN ANALYZE
SELECT * FROM big_a a JOIN big_b b ON a.key = b.key;
-- Hash Join (cost=10000..50000)
-- -> Seq Scan on big_a
-- -> Hash
-- -> Seq Scan on big_bКогда хеш-соединение выигрывает
Две таблицы среднего или большого размера, отсутствие хорошего индекса по ключу соединения или необходимость получить много строк по оценке планировщика. Ограничение по памяти: хеш-таблица должна помещаться в work_mem, иначе она выгружается на диск.
Соединение слиянием
Обе стороны отсортированы по ключу соединения и проходят вместе. Отлично подходит, когда обе стороны уже отсортированы, например индексом с подходящим порядком:
EXPLAIN ANALYZE
SELECT * FROM big_a a JOIN big_b b ON a.key = b.key
ORDER BY a.key;
-- Merge Join
-- -> Index Scan on big_a (a.key ASC)
-- -> Index Scan on big_b (b.key ASC)Когда соединение слиянием выигрывает
Два больших предварительно отсортированных набора входных данных. Линейное сканирование, небольшой расход памяти. Стоимость сортировки важна — если обе стороны нужно сортировать явно, хеш-соединение обычно выигрывает.
Выбор стратегии
Планировщик выбирает стратегию на основе:
- Оценочного числа строк
- Доступных индексов
- Памяти (
work_mem) - Констант стоимости в postgresql.conf
Принудительный выбор стратегии (только для диагностики)
Для отладки можно отключить стратегии:
SET enable_hashjoin = off;
SET enable_mergejoin = off;
SET enable_nestloop = off;
-- Re-run EXPLAIN to see what the planner picks instead.
-- NEVER persist these in production.Выгрузка на диск
Если хеш-таблица или сортировка превышает work_mem, оператор выгружает временные файлы на диск — это намного медленнее. Либо увеличьте work_mem, либо перепишите запрос.
Параллельные соединения
PostgreSQL может выполнять хеш-соединение и соединение слиянием параллельно (а также последовательное сканирование и сканирование по индексу) — это видно по Parallel Hash Join с Workers Planned в EXPLAIN.
Как читать выбранную стратегию
В EXPLAIN ANALYZE имя узла соединения сообщает выбранную стратегию. Почти всегда выбор правилен — если это не так, сначала проверьте статистику и индексы, а уже потом принудительно задавайте стратегии.
Итоги
Три стратегии соединения подходят для разных ситуаций.
- Вложенный цикл: небольшая внешняя часть + индексированная внутренняя
- Хеш: большие таблицы, нет полезного индекса
- Слияние: предварительно отсортированные входные данные
Быстрая проверка
Вы соединяете две таблицы по 10 миллионов строк по неиндексированному столбцу. Какой алгоритм соединения, скорее всего, выберет планировщик?
Часто задаваемые вопросы
Урок «Хеш-соединение, соединение слиянием и вложенный цикл» бесплатный?
Да — полный текст урока «Хеш-соединение, соединение слиянием и вложенный цикл» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс SQL Academy, подпишись на CoddyKit PRO. Курс SQL Academy содержит 4 уроков всего.
Чему я научусь в уроке «Хеш-соединение, соединение слиянием и вложенный цикл»?
Познакомьтесь с тремя основными стратегиями соединения, их профилями стоимости и условиями, при которых планировщик выбирает каждую из них Ты практикуешь SQL Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.
Нужен ли мне опыт, чтобы начать SQL Academy?
Предыдущий опыт не требуется. SQL Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 3 из 4.
Сколько времени занимает урок «Хеш-соединение, соединение слиянием и вложенный цикл»?
Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.
Можно ли писать и запускать код в этом уроке SQL Academy?
Да. Каждый урок SQL Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.
Все уроки этого курса
- Чтение EXPLAIN и EXPLAIN ANALYZE
- Последовательное сканирование и сканирование по индексу
- Хеш-соединение, соединение слиянием и вложенный цикл
- Поиск и исправление медленных запросов