docs: document parallel_copy + full bench benchmark (#300) - #326
Conversation
…ommandprompt#300) parallel_copy (commandprompt#300, shipped in commandprompt#323 + commandprompt#324) had no user-facing docs -- it existed only in the SQL COMMENT. Document it: - features.md, user-guide.md, sql-reference.md: describe parallel_copy, its two target kinds (single columnar table = any order; RANGE-partitioned = file sorted by the partition key, numeric/temporal key), atomicity via 2PC, privileges (pg_read_server_files + INSERT), and the max_prepared_transactions requirement. - limitations.md: the constraints (text format only, target kinds, sorted-key requirement, core-count plateau, 2PC in-doubt window). - benchmarks.md: a full ingest benchmark from the bench (pg18n, 20M + 100M TSBS, median of 3 interleaved rounds). Single table: COPY 129.8s -> 8w 20.6s (6.29x), 16w 6.87x; 100M: COPY 644.1s -> 16w 92.8s (6.94x); partitioned 20M: 8w 4.61x, 16w 5.27x. Identical rows/checksum; on-disk within 0.03%. - CHANGELOG.md: the feature entry under Added. Also fix two stale inline comments that outlived the single-table work: - the SQL COMMENT still said 'RANGE-partitioned' only; - a comment in columnar_parallel_copy.c claimed single-table was 'a planned enhancement' directly above the code that implements it. Docs pass test/ste_check.py; no behavior change. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UX1jrWiQsJJA1t4pkmkb4T
Review: accurate and honest. One missing restriction, and it is a surprising one.I checked the documented restrictions against the code rather than reading them for Everything stated checks out. In particular the line I most expected to be
The rest matches too: text format only, the two accepted target shapes, sorted input The 2PC paragraph is the part I would have been tempted to soften and you did not:
That is the honest description of the window, and naming Also right to fix the stale code comment and the SQL The gap:
|
…on (commandprompt#300) jdatcmd's commandprompt#326 review: 'atomic' can mislead. The load runs in background workers and commits independently, so it is NOT part of the calling transaction -- a caller ROLLBACK does not undo it, and there is no PreventInTransactionBlock guard. Verified on pg18a assert: BEGIN; parallel_copy(...5000 rows); ROLLBACK; leaves all 5000 rows, 0 prepared leaked. Document it where atomicity is discussed (limitations, sql-reference, user-guide). The atomicity is across the workers, not with the caller. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UX1jrWiQsJJA1t4pkmkb4T
|
Confirmed and fixed in So the rows survive the caller's Documented where "atomic" appears, so a reader meets the caveat at the claim rather than later:
On |
parallel_copy(#300, shipped in #323 and #324) had no user-facing documentation — it existed only in the SQLCOMMENT. This documents it and adds a full ingest benchmark from the bench.Docs added
max_prepared_transactionsrequirement and the sorted-key rule for partitioned targets.pgcolumnar.parallel_copy(target, path [, workers])entry: the two target kinds (single columnar table = any row order; RANGE-partitioned = file sorted ascending by a numeric/temporal partition key), atomicity via 2PC, and thepg_read_server_files+ INSERT privileges.Full bench benchmark (benchmarks.md)
Bench, PostgreSQL 18.4 non-assert, 16 vCPU / 8 physical cores / 62 GB. TSBS cpu, 21 columns, sorted by time. Median of three interleaved rounds, source file warm. Baseline is one server-side
COPY.Single columnar table, 20M rows:
Plateau at the 8 physical cores; the encode is CPU-bound. All runs load 20,000,000 rows with an identical
sum(usage_user); on-disk size varies 0.03% as the split shifts a few stripe boundaries.100M rows: one
COPY644.1 s vsparallel_copy(16)92.8 s = 6.94x; both 2.67 GB (within 0.004%). Row counts match; the floatsummatches to nine figures and differs in the last, because parallel summation adds in a different order.RANGE-partitioned, 20M rows, 24 hourly partitions: COPY 134.0 s vs 8w 29.1 s (4.61x), 16w 25.4 s (5.27x). Partition routing costs a little more than the single-table split.
Also: two stale inline comments
Found while auditing. Both outlived the single-table work in #324:
COMMENTstill described the target asRANGE-partitionedonly;columnar_parallel_copy.csaid single-table parallel load was "a planned columnar-core enhancement" directly above the code that implements it.Validation
test/ste_check.pypasses on every changed doc.docs_styleandparallel_copy.