Record what the external validation established (#437) - #440
Conversation
) Four changes, each backed by a measurement rather than by the report alone. aarch64 is no longer untested. limitations.md said every recorded result comes from x86_64 and the suites have never run on aarch64 (commandprompt#242). An independent gate on a Graviton3 host passed every suite with the same per-suite result as x86_64. The big-endian half of that sentence stays true and stays. The owner asked that the arm against x86 timing ratios not be published, so they are not here. The correctness update is a different claim and it is. stripe_row_limit is documented as the setting that governs fetch-by-index cost, with the sweep and with its cost. chunk_group_row_limit is named explicitly as NOT the setting for this, because the external report recommended it and it does nothing here: isolated one knob at a time, chunk_group alone moved a point lookup from 245.4 ms to 252.3 ms, and stripe_row_limit alone moved it to 19.3 ms. The floor is stated with the benefit. Below 10000 rows a selective range query regresses, because a smaller row group makes more metadata to read. A tuning knob documented without its cost is a trap. Cross-architecture portability is stated as narrowly as the format supports. The native format stores integers in HOST byte order, which the format specification says at line 11 and columnar.h:57 repeats. The validation moved a data directory from x86_64 to aarch64 and read it correctly, but both are little-endian, so that test cannot distinguish portable from host-endian. The docs now say same byte order, note that PostgreSQL's own heap format has the same rule, and say a big-endian move is unsupported and untested. index.md gains a "when not to use pgColumnar" section from the reporter's ledger numbers, attributed to them. It keeps the two rows where columnar still wins, because a section that lists only losses is not the honest version. Logical replication limitations are deliberately absent: commandprompt#439 is writing those. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UqprqkCXuH8SegiZejE1Tw
|
Added one more, found while verifying the portability claim.
The code does. A data directory does not. That sentence sat in the one section a reader consults before moving a cluster, and it contradicted the portability text this PR was adding to Both now say the same thing: same byte order, the same rule PostgreSQL's own heap format follows, and a big-endian move unsupported and untested. The section also picks up the aarch64 update, since that is where a reader looks for it. Separately: |
5d53676 to
2cec721
Compare
…at does not (commandprompt#437) The Host architecture section said "The rest of the extension runs on any architecture PostgreSQL supports." The CODE does. A DATA DIRECTORY does not. The native format stores multi-byte values in host byte order. The format specification says so at line 11, and columnar.h:57 repeats it. So the sentence was true about the binary and misleading about the data, in the one section a reader consults before moving a cluster. This is the same claim added to administration.md in the previous commit, in the section that contradicted it. Both now say the same thing: same byte order, the same rule PostgreSQL's own heap format follows, and a big-endian move unsupported and untested. It also picks up the aarch64 update, since this section is where a reader looks for it. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UqprqkCXuH8SegiZejE1Tw
2cec721 to
3e4827d
Compare
jdatcmd
left a comment
There was a problem hiding this comment.
Verified the load-bearing claim independently, on a different fixture. It holds.
The claim that would send people the wrong way if wrong is "stripe_row_limit governs
fetch cost, chunk_group_row_limit does not". I isolated one knob at a time on my own
fixture, 200,000 rows, median of five random point lookups:
| configuration | size | point lookup |
|---|---|---|
| defaults | 4480 kB | 111 ms |
chunk_group_row_limit=1000 only |
4480 kB | 133 ms, no effect |
stripe_row_limit=10000 only |
4584 kB | 23 ms |
stripe_row_limit=2000 only |
5224 kB | 12 ms |
Same conclusion as yours, and worth more than a repeat because my fixture compresses and
yours does not: 4.5 MB against your 527 MB for a comparable row count, because my blob is
hex and yours was incompressible. The knob's behaviour is the same on both shapes, which is
a stronger claim than either measurement alone.
Documenting a knob as ineffective is exactly the kind of statement that deserves a second
fixture, since a reader will act on it and never re-measure.
One number a reader may over-generalise
Your text says of the smaller row group:
Size grows by 0.4 percent at 2000 rows.
On incompressible data, which the paragraph does state. On my compressible fixture the
same setting cost 16 percent (4480 kB to 5224 kB). Both are correct for their data, and
the reason is the same one your ClickBench prefix finding turns on: fixture shape decides
the answer.
Not blocking, and the fixture is named right above the table. A clause noting the overhead
is larger when the data compresses would stop someone reading 0.4 percent as a general
property. Your call.
The rest
"When not to use pgColumnar" is the most valuable section in this PR. A 200x point
lookup and a 24x ordered segment scan, published beside the 2.3x aggregate win, is worth
more to a prospective user than any benchmark that only shows the good shapes. Keeping the
last two rows in the same table, with "read the last two rows with the others", is the
right presentation.
The aarch64 correction is properly scoped. Suites pass, byte order unchanged, big-endian
still untested and still said so. Withholding the arm-versus-x86 timing ratios at the
owner's request is right too: correctness and performance are different claims and only one
was established.
All 12 pages pass docs_style.sh. Approving.
Closes #437. @jdatcmd for review.
Four documentation changes from the external validation report, each backed by a
measurement rather than by the report's word. All 12 docs pages pass
docs_style.sh.1. aarch64 is no longer untested
docs/limitations.mdsaid every recorded result comes from x86_64 and the suites havenever run on aarch64 (#242). The independent gate ran the full suite on a Graviton3 host
and every suite passed, with the same per-suite result as x86_64. The big-endian half of
that sentence is still true and stays.
The owner asked that the arm against x86 timing ratios not be published, so they are
not here. Graviton being slower on scan paths is not a finding anyone needs. The
correctness update is a different claim and it is in.
2.
stripe_row_limitis documented as the fetch-cost knob, andchunk_group_row_limitis named as not being itThe report recommends
chunk_group_row_limitfor point-lookup-heavy tables. It doesnothing. Isolated one knob at a time on a 511 MB blob-heavy fixture:
chunk_group_row_limit1000 onlystripe_row_limit10000 onlyBoth the reporter and my own first measurement changed the two together and could not tell
them apart. The docs now name the right one and say the other is not it, because the advice
as published would send people to tune a knob that does not move this.
3. The knob's cost is stated with its benefit
stripe_row_limitSize grows 0.4 percent, scan throughput does not change, and there is a floor: a
selective range query was slower at 2000 than at 10000, because a smaller row group makes
more metadata to read. A tuning knob documented without its cost is a trap, so the floor is
in the same paragraph as the win.
4. Cross-architecture portability, stated as narrowly as the format supports
This is the one I would look at hardest.
The report moved a data directory from x86_64 to aarch64 and read it correctly, and
suggested a docs line. Both of those are little-endian, so that test cannot distinguish
"portable" from "host-endian and both hosts agree."
It is host-endian, deliberately, and both the spec and the header say so:
PgColumnarEncodeValuewrites fixed-width values withstore_att_byval, which is the rawhost representation. The one
#ifdef WORDS_BIGENDIANin the tree(
columnar.h:919-926) mirrors PostgreSQL's in-memory varlena header layout and has nothingto do with the on-disk format.
So the docs say same byte order, not "across architectures". They also say
PostgreSQL's own heap format follows the same rule, because that is the point: a columnar
table is no more restricted than the rest of the cluster, and a reader should not come away
thinking this is a pgColumnar limitation.
5. A "when not to use pgColumnar" section
docs/index.md, from the reporter's ledger numbers and attributed to them. It keeps the tworows where columnar still wins (1.27x smaller, 2.3x faster on the narrow aggregate), because
a section listing only losses is not the honest version of it.
Deliberately absent
Logical replication limitations. #439 is writing those and I am not going to collide with it.
🤖 Generated with Claude Code