Finish the plan-shape sweep #203 started - #207
Conversation
jdatcmd#203 asserted the node in the three files that were asked for, and named the rest as a sweep left undone. This is the rest of it. Six more suites read a counter out of EXPLAIN and assert on the number: native_skip, native_bloom, native_cluster, native_recluster, sorted_projection, write_minmax_fastpath Those counters -- "Columnar Chunk Groups Removed by Filter" and "Columnar Vectors Skipped" -- exist only on the columnar custom scan. When the planner stops choosing it the read returns nothing, and the check fails describing skipping, or bloom, or clustering: anything except the plan change that actually happened. The helper moves to test/lib.sh as pgc_is_columnar_scan rather than being copied six times, and uses EXPLAIN without ANALYZE, since the marker line comes from the plan and not the run -- so an assertion costs a plan and does not execute the query. It greps positively for the node's own marker rather than testing for absence: a plan that fell back to a sequential scan has no Columnar lines to be absent, so an absence test would pass for exactly the case worth catching. Two suites in the survey are deliberately left alone: - analyze_stats reads "Rows Removed by Filter", a generic executor counter, and compares the same query with and without an index. Its comment says the comparison is independent of plan shape, and it is; asserting a node there would contradict what the check is for. - audit greps for "Pushed-Down Filters: 1" and requires the value. That cannot pass without the node, so only the failure message would improve, and not enough to justify touching that file. Verified by taking the node away. With enable_custom_scan off, every one of the six fails its node assertion ahead of the counter checks that assertion guards, while the parity checks around them keep passing -- which is the point: parity cannot see a plan change, so before this the first red line in each file described the wrong thing.
|
Status update: the red this PR disclosed is gone, and it was the contention flake, exactly as the PR said. When I opened this, its gate was red on Re-gated the state the merge button produces —
So the branch is green on current |
jdatcmd
left a comment
There was a problem hiding this comment.
Approving.
The helper is right and I checked the two things that could make it quietly wrong:
- Positive grep, not absence.
Columnar Projected Columnsis the node's own marker; a plan that fell back to a seqscan has noColumnarline, so an absence test would pass for exactly the case worth catching. You got this the correct way round. - The aggregate queries still carry the marker.
sorted_projectionandwrite_minmax_fastpathassert on aggregate/groups-removed queries, and the concern would be that a vectorized aggregate plan reportsColumnar Vectorized Aggregatesinstead ofColumnar Projected Columns, which would make the new check fail on a normal run. It doesn't — those two suites pass on both majors in your gate, and a passing normal run is itself the proof the marker appears for those queries. The underlying scan still projects under the aggregate.
EXPLAIN without ANALYZE is the right call and you confirmed the line is planner-sourced rather than assuming it. Proof by removal in both directions (fallback fails the node check ahead of the counters it guards; normal passes) is exactly the standard.
On the red
Not this change, and now demonstrably not a fixture-of-the-week either. native_fetch_position is in is_timing_suite as of #209 (merged), so on current main it runs serially, after the parallel batch. Your PR does not touch it. Its 2.11-vs-2.0 was the six-way contention you diagnosed, measured against your own alone: 1.08–1.17 — the harness measuring itself. Re-gating this branch on main now carries the serialization and should clear it.
Your root-cause section is worth more than the PR, and it is the right frame: "passes on an idle box" is not a property this gate can observe, because it is never idle. #204 and #209 took two of the three; native_fetch_position and native_cancel want the same headroom-not-argument treatment. I'd take you up on that offer.
Merging — test-only, correct, and the only red is a now-serialized suite it does not touch.
#203 asserted the node in the three files you named and I flagged the rest as a sweep left undone. This is the rest of it.
What was exposed
I surveyed all 28 suites that read
EXPLAIN, narrowed to the 13 that pull a numeric counter out of it and assert on the number, and found six with no node assertion at all:native_skip,native_bloom,native_cluster,native_recluster,sorted_projection,write_minmax_fastpathColumnar Chunk Groups Removed by FilterandColumnar Vectors Skippedare reported by the columnar custom scan and by nothing else. When the planner stops choosing it, the read returns nothing and the check fails describing skipping, or bloom, or clustering — anything except the plan change that actually happened.The helper
In
test/lib.shaspgc_is_columnar_scan, once rather than copied six times.It uses
EXPLAINwithoutANALYZE: the marker line comes from the plan rather than the run, which I confirmed rather than assumed, so the assertion costs a plan and does not execute the query. And it greps positively for the node's own marker rather than testing for absence — a plan that fell back to a sequential scan has noColumnarlines to be absent, so an absence test would pass for exactly the case worth catching.Two suites deliberately left alone
analyze_statsreadsRows Removed by Filter, a generic executor counter, and compares the same query with and without an index. Its own comment says the comparison is independent of plan shape, and it is. An assertion there would contradict what the check is for.auditgreps forPushed-Down Filters: 1and requires the value, so it cannot pass without the node. Only the failure message would improve, and not enough to justify touching that file.Verified by taking the node away
With
enable_custom_scan=off, every one of the six fails its node assertion ahead of the counter checks that assertion guards, while the parity checks around them keep passing — which is the point, since parity cannot see a plan change:Gate — read this part
native_fetch_positionand nothing else.I am not going to describe that as green. The failing check is
doubling the row group does not double the cost of the same fetches, atsmall=97ms big=205ms— a ratio of 2.11 against a 2.0 bound. Nothing of mine was running alongside it; I had stopped everything for the gate.It is not this change — this is test-only and does not touch that suite — and here is that claim measured rather than asserted. The same check, run on its own, four times on each side:
The root cause, which is worth more than this PR
run_all_versions.shruns six suites concurrently:So every wall-clock ratio in the matrix is measured against five other suites and their clusters. "Passes on an idle box" is not a property the gate can ever observe — the gate is never idle, by design.
That reframes the three flaky timing suites of this session. They are not three thin fixtures that met three unlucky boxes; they are three wall-clock ratios measured under six-way concurrency, and the ~1.8x inflation above is the harness measuring itself. #204 fixes one of them properly by giving the fixture forty points of headroom instead of arguing about the box. The other two want the same treatment, and I would rather that be a deliberate follow-up than something I bolt onto a test-only sweep.
Happy to take
native_fetch_positionandnative_cancelnext on the same principle if you want them.