| From: | PG Bug reporting form <noreply(at)postgresql(dot)org> |
|---|---|
| To: | pgsql-bugs(at)lists(dot)postgresql(dot)org |
| Cc: | manuelreyesbravo(at)gmail(dot)com |
| Subject: | BUG #19639: EXPLAIN (FORMAT JSON) emits a 309-digit cost value, and the node still reports "Disabled": false |
| Date: | 2026-08-23 23:46:57 |
| Message-ID: | 19639-9b1c9624a6034702@postgresql.org |
| Views: | Whole Thread | Raw Message | Download mbox | Resend email |
| Thread: | |
| Lists: | pgsql-bugs |
The following bug has been logged on the website:
Bug reference: 19639
Logged by: Manuel Reyes Bravo
Email address: manuelreyesbravo(at)gmail(dot)com
PostgreSQL version: 19beta3
Operating system: Fedora 44, Linux 7.1.8, gcc 16.1.1, PostgreSQL bui
Description:
Note up front: reproducing this needs a third-party index access method, but
what I am reporting is the EXPLAIN output itself. Whatever the origin of the
cost value, EXPLAIN (FORMAT JSON) emitting a 309-digit numeric literal
breaks
JSON consumers, and that part is in core. See "On attribution" at the end
for
what I did and did not verify.
On 19beta3, EXPLAIN (FORMAT JSON) can emit a cost of DBL_MAX, rendered as a
309-digit number. serde_json rejects it with "number out of range", and I
would
expect most plan-analysis tooling to have the same problem, since there is
no
way for a client to consume it other than parsing the number as text.
There is a second, separate oddity in the same output: the node carries
"Disabled": false while having that saturated cost. On 18.6 the same query
gets an ordinary cost and the disabled node is marked as disabled, which is
what the disabled-nodes mechanism exists for.
Reproducer
----------
Using pgvectorscale 0.9.0 ("diskann") with pgvector 0.8.6:
CREATE EXTENSION vector;
CREATE EXTENSION vectorscale;
CREATE TABLE t_quant (
id SERIAL PRIMARY KEY,
embedding vector(3),
labels SMALLINT[]
);
CREATE INDEX idx_quant ON t_quant USING diskann (embedding, labels);
INSERT INTO t_quant (embedding, labels) VALUES
('[1,2,3]', '{1,2}'), ('[4,5,6]', '{1,3}'), ('[7,8,9]', '{2,3}');
SET enable_seqscan = 0;
EXPLAIN (FORMAT JSON)
SELECT * FROM t_quant
WHERE labels && '{1}'
ORDER BY labels, embedding <=> '[0,0,0]';
Ordering by labels first is the point: the index cannot satisfy that
ordering,
so with enable_seqscan off the only remaining plan is a penalized one.
19beta3:
"Node Type": "Sort"
"Total Cost": 179769313486231570814527423731704356798... (309 digits)
"Disabled": false
"Node Type": "Index Scan"
"Total Cost": 179769313486231570814527423731704356798... (309 digits)
"Disabled": false
18.6 (same extension, same schema, same query):
"Node Type": "Sort"
"Total Cost": 20.64
"Disabled": false
"Node Type": "Seq Scan"
"Total Cost": 20.63
"Disabled": true
The text format shows the same value, with the cost running off the line.
Two issues, I believe
---------------------
1. Regardless of how the cost became that large, EXPLAIN (FORMAT JSON)
producing a 309-digit numeric literal is a problem in itself. JSON
consumers
are not prepared for it.
2. "Disabled": false together with a saturated cost is self-contradictory.
Since the disabled-nodes mechanism was introduced precisely so that
disabling a node no longer required inflating its cost, seeing both
suggests
something is not going through that mechanism.
On attribution
--------------
What I measured: 19beta3 emits this and 18.6 does not, with identical
extension
code, schema and query.
What I did not determine: where the value originates. It is possible that
the
AM's amcostestimate returns a very large cost and that 19 propagates it
while
18 never generated that path at all (18 picks a sequential scan instead). So
I
am not claiming the root cause is in core -- but issue 1 seems worth
addressing
either way, and issue 2 looks like a genuine inconsistency in the output.
Versions tested
---------------
PostgreSQL 19beta3, built from source: as shown above
PostgreSQL 18.6, built from source with the same compiler and flags:
normal costs
Happy to dig further if someone points me at the right place to look.
| From | Date | Subject | |
|---|---|---|---|
| Next Message | zengman | 2026-08-24 03:37:13 | Re:BUG #19625: SQL/JSON boolean DEFAULT expression silently replaced with 'false' |
| Previous Message | PG Bug reporting form | 2026-08-23 23:45:47 | BUG #19638: Planner chooses an index-only scan for an index AM without amcanreturn, and execution fails |