Выбор ответа Senior EXPLAIN и оптимизация обновлено

Что значит Batches: 2 у узла Hash

Вопрос

Запрос выполнялся с work_mem = '1MB'. Что означает Batches: 2 у узла Hash и как это обычно лечат?

HashAggregate  (cost=37048.22..37048.29 rows=5 width=49) (actual time=577.354..577.359 rows=5 loops=1)
  Group Key: c.city
  Batches: 1  Memory Usage: 24kB
  ->  Hash Join  (cost=1956.00..32048.22 rows=1000000 width=24) (actual time=11.246..437.444 rows=1000000 loops=1)
        Hash Cond: (o.customer_id = c.id)
        ->  Seq Scan on orders o  (cost=0.00..17408.00 rows=1000000 width=11) (actual time=0.014..102.939 rows=1000000 loops=1)
        ->  Hash  (cost=1038.00..1038.00 rows=50000 width=21) (actual time=11.087..11.088 rows=50000 loops=1)
              Buckets: 32768  Batches: 2  Memory Usage: 1633kB
              ->  Seq Scan on customers c  (cost=0.00..1038.00 rows=50000 width=21) (actual time=0.003..3.865 rows=50000 loops=1)
Planning Time: 1.089 ms
Execution Time: 577.587 ms

Попробуйте сами

Выберите вариант, и откроется разбор.

Показать ответ и разбор

Коротко

Правильный ответ: В хеше слишком много коллизий; нужно увеличить число Buckets вручную. Hash Join строит хеш-таблицу по меньшей стороне.

Варианты ответа

  1. Хеш-таблицу собирали два параллельных воркера; лечить ничего не нужно
  2. Таблица customers прочитана дважды из-за плохой статистики; нужен ANALYZE
  3. Хеш не влез в память, соединение разбито на 2 партии; поднять work_mem
  4. В хеше слишком много коллизий; нужно увеличить число Buckets вручнуюправильный ответ

Разбор

Hash Join строит хеш-таблицу по меньшей стороне. Если она не влезает в лимит памяти (work_mem × hash_mem_multiplier, множитель по умолчанию 2 начиная с PostgreSQL 15), строки делятся на партии (batches): одна обрабатывается в памяти, остальные пишутся во временные файлы и дочитываются потом. Batches: 1 значит, что всё поместилось. Лечат точечным SET work_mem для тяжёлого отчёта, выбором меньшего числа колонок (в хеш попадают только нужные) или фильтрацией до соединения. Параллельность в плане видна по узлам Gather и Parallel, здесь их нет. Число бакетов PostgreSQL подбирает сам, а повторного чтения таблицы план не показывает.

Ответьте сами, а не прочитайте

В тренажёре вопрос попадёт в повторения и вернётся, когда начнёт забываться. Плюс билеты с зачётом: 20 вопросов, не больше 2 ошибок.

Термины по теме