linuxlab.io
Учебники▾
  • Линукс и сети
    Файловая система, процессы, TCP/IP, BGP и OSPF
    →
  • Terraform и IaC
    HCL, state, plan/apply на sandbox LocalStack
    →
  • Git и GitHub
    Объектная модель, plumbing, ветвление, GitHub Actions
    →
Все учебники →
ЦеныО платформеВойтиСоздать аккаунт
/
Intro
Lessons
Footer
linuxlab-УчебникиЦеныО платформеКонфиденциальность и куки
Copyright © 2026 LinuxLab. Все права защищены.
linuxlab.io
Учебники▾
  • Линукс и сети
    Файловая система, процессы, TCP/IP, BGP и OSPF
    →
  • Terraform и IaC
    HCL, state, plan/apply на sandbox LocalStack
    →
  • Git и GitHub
    Объектная модель, plumbing, ветвление, GitHub Actions
    →
Все учебники →
ЦеныО платформеВойтиСоздать аккаунт
/
  • Введение
  • Главы
  • How it worksскоро
  • Уроки
  • База знаний
  • Собеседование
home/postgres/kb/Планировщик и оптимизатор/join-algorithms

kb/planner ── Планировщик и оптимизатор ── intermediate

Алгоритмы соединения: nested loop, hash, merge

Nested loop хорош при малом внешнем входе и индексе внутри; hash join - для больших входов по равенству (нужен work_mem); merge join - когда входы уже отсортированы. Memoize кеширует поиски nested loop.

view as markdownaka: join-types, nested-loop, hash-join, merge-join

Три алгоритма

АлгоритмЛучший случайСложность
Nested loopмал внешний вход + индекс на внутреннейO(N×M), с индексом O(N×log M)
Hash joinбольшие входы, соединение по =O(N+M)
Merge joinвходы уже отсортированы по ключуO(N+M) после сортировки

Nested loop для каждой внешней строки ищет совпадения во внутренней; с индексом на ключе внутренний поиск точечный. Hash join строит хеш по меньшему входу в work_mem, зондирует большим; только для равенства. Merge join сливает два отсортированных входа за проход; почти бесплатен, если сортировка не нужна.

work_mem и пролив на диск

Если хеш не влезает в work_mem, join делит вход на batches и проливается на диск. В EXPLAIN ANALYZE:

Hash  Buckets: 4096  Batches: 8  Memory Usage: 4096kB

Batches: 1 - всё в памяти; больше - был пролив, join медленнее.

Memoize

Узел Memoize кеширует результаты внутреннего поиска nested loop по ключу - выгоден при повторяющихся и перекошенных ключах.

Упорно плохой выбор алгоритма почти всегда значит неверную кардинальность (см. planner-statistics), а не плохой алгоритм. Тумблеры enable_* - для диагностики, не для прода. Выбор порядка соединений - в join-order-geqo.

§ команды

bash
EXPLAIN SELECT * FROM a JOIN b USING(id);

Посмотреть выбранный алгоритм соединения

bash
SET enable_hashjoin = off;

Увести план с hash на merge/nested (для учёбы/диагностики)

bash
SET work_mem = '64MB';

Больше памяти под хеш/сортировку - меньше пролива на диск

§ см. также

  • join-order-geqoПорядок соединений, GEQO и кеш планаЧисло порядков соединения растёт быстрее факториала; до geqo_threshold (12) планировщик ищет порядок динамическим программированием, дальше - генетическим GEQO. Кеш плана: после ~5 вызовов custom может стать generic.
  • access-methodsМетоды доступа: Seq, Index, Bitmap, Index-OnlyЧетыре способа достать строки: Seq Scan (всё подряд), Index Scan (мало строк, random I/O), Bitmap Heap Scan (средняя доля, страницы пачкой), Index-Only Scan (данные из индекса, если visibility map подтверждает).
  • planner-statisticsСтатистика планировщика: pg_statsПланировщик не читает данные при планировании - берёт сводку из pg_statistic (view pg_stats), собранную ANALYZE: null_frac, n_distinct, MCV с частотами и гистограмму равной площади. Устаревшая сводка - частый корень плохих планов.
Footer
linuxlab-
Copyright © 2026 LinuxLab. Все права защищены.
Учебники
Цены
О платформе
Конфиденциальность и куки