Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

ES013: Planner settings force the plan

  • Signal: the plan was made with an enable_* setting turned off, such as enable_seqscan = off, which the plan’s Settings show (EXPLAIN (SETTINGS)), or the planner used a node that such a setting disables because it found no other way: PostgreSQL 18 marks the node Disabled: true, and before 18 its estimated cost includes the 10¹⁰ PostgreSQL adds for each disabled node.
  • Evidence: the settings, how the node is known to be disabled, and the time in the node.
  • Action: reset the settings (RESET enable_seqscan, or a new session) and run EXPLAIN again: applications that plan with the defaults may get another plan. A setting made for a role or a database (ALTER ROLE or ALTER DATABASE … SET) applies to every session. To test a plan, SET LOCAL keeps a setting to one transaction.
  • Severity: always medium. The finding says nothing about the plan’s speed, but the plan may not be the one applications get.
  • Stays silent when: neither such settings nor a disabled node show. Settings that tune rather than take choices away, such as work_mem, random_page_cost or max_parallel_workers_per_gather, are not flagged.

Example

The group_aggregate scenario of the test corpus, captured on PostgreSQL 16: sorted GROUP BY (group aggregate) with hash aggregation disabled.

SELECT country, count(*) FROM customers GROUP BY country;
GroupAggregate  (cost=1834.77..1984.87 rows=10 width=11) (actual time=8.896..10.953 rows=10 loops=1)
  Output: country, count(*)
  Group Key: customers.country
  Buffers: shared hit=209
  ->  Sort  (cost=1834.77..1884.77 rows=20000 width=3) (actual time=8.627..9.450 rows=20000 loops=1)
        Output: country
        Sort Key: customers.country
        Sort Method: quicksort  Memory: 1081kB
        Buffers: shared hit=209
        ->  Seq Scan on public.customers  (cost=0.00..406.00 rows=20000 width=3) (actual time=0.008..2.751 rows=20000 loops=1)
              Output: country
              Buffers: shared hit=206
Settings: enable_hashagg = 'off', max_parallel_workers_per_gather = '0'
Planning:
  Buffers: shared hit=76
Planning Time: 0.368 ms
Execution Time: 11.102 ms

explainsql reports:

MEDIUM  ES013 Planner settings force the plan
The plan was made with enable_hashagg = off, which keeps the planner from some of its usual choices.
Settings: enable_hashagg = off
→ Applications that plan with the defaults may get another plan: reset it (RESET enable_hashagg, or a new session) and run EXPLAIN again. If a role or a database sets it (ALTER ROLE or ALTER DATABASE … SET), every session plans this way; to test a plan, SET LOCAL keeps a setting to one transaction.

All rules