| From: | Manuel Reyes Bravo <manuelreyesbravo(at)gmail(dot)com> |
|---|---|
| To: | imchifan(at)163(dot)com, pgsql-bugs(at)lists(dot)postgresql(dot)org |
| Subject: | Re: BUG #19692: Generic partition-pruning plan delays statement_timeout cancellation |
| Date: | 2026-09-17 22:40:44 |
| Message-ID: | CA+bCEdAwPdtg6D-kePW+HeuJQZdqy=N9XXS5CFeHyNg1=Aux2A@mail.gmail.com |
| Views: | Whole Thread | Raw Message | Download mbox | Resend email |
| Thread: | |
| Lists: | pgsql-bugs |
PG Bug reporting form <noreply(at)postgresql(dot)org> wrote:
> Generating a fresh generic plan for a range-partitioned table with 18
> partition keys and two parameterized lower-bound clauses per key delays
> statement_timeout cancellation. With statement_timeout set to 50 ms,
> cancellation was not reported until 315-346 ms after the statement began.
Reproduced on master (e1d8f81d496), built with --enable-debug
--enable-cassert, so the absolute numbers here are larger than they would
be on a production build:
psql reports the error after 281-304 ms, five runs, statement_timeout 50ms.
> Inference: this predicate shape appears to generate a Cartesian expansion of
> partition-pruning clause prefixes without sufficiently frequent interrupt
> checks.
That is where the time goes, and there are no interrupt checks at all:
partprune.c has no CHECK_FOR_INTERRUPTS(). Instrumenting
gen_partprune_steps() to log elapsed time against the statement start on
the case above:
gen_partprune_steps entered at 0.383 ms
first recursive call at 0.402 ms
gen_partprune_steps returned at 130.026 ms, after 524250 recursive calls
get_steps_using_prefix_recurse() emits one pruning step per combination of
the clauses matched to each partition key, so with 18 keys and 2 clauses
per key the recursion runs ~2^19 times. None of those calls services a
pending cancellation.
The attached patch adds a CHECK_FOR_INTERRUPTS() to that recursion, for the
same reason commit 35313832248 added one to the planner in 2005 ("you can't
Query-Cancel a long planner run, because no part of the planner did
CHECK_FOR_INTERRUPTS()").
It is worth separating two things that the client-side number adds
together. Timing the server itself, with log_statement=all, and taking the
distance between the "statement:" log line and the timeout error:
server raises the error at
master 135 ms
master + patch 50 ms (statement_timeout = 50 ms)
So with the patch the backend honors the deadline. psql still reports
115 ms rather than 50 ms, but that remaining time elapses *after* the error
is raised, while the transaction aborts and the memory for the steps built
so far is released; it is not planner work that fails to check for
interrupts, and no additional CHECK_FOR_INTERRUPTS() will shorten it. I
have not looked into whether that part is worth doing anything about.
Adding a check to the loop in get_matching_partitions() as well made no
measurable difference on this case, because with the patch the statement is
already cancelled during step generation and never reaches it.
Tests: test_setup, create_index, partition_prune, partition_join and
inherit pass with the patch.
Regards,
Manu
| Attachment | Content-Type | Size |
|---|---|---|
| bug19692-0001-Make-partition-pruning-step-generation-interruptible.patch | text/x-patch | 1.7 KB |
| From | Date | Subject | |
|---|---|---|---|
| Next Message | Tender Wang | 2026-09-18 02:02:42 | Re: wrong results: merge when not matched by source |
| Previous Message | Daniel Gustafsson | 2026-09-17 22:24:15 | Re: Postmaster crashes on SIGHUP when oauth_validator_libraries holds only whitespace |