Add TPC-DS SLT tests with plans and Parquet parity - #9804
Conversation
Merging this PR will degrade performance by 7.04%
|
| Mode | Benchmark | BASE |
HEAD |
Efficiency | |
|---|---|---|---|---|---|
| ❌ | Simulation | random_i8[0.5] |
67.8 µs | 91.4 µs | -25.83% |
| ❌ | WallTime | words_gather_scalar_avx2[65536] |
8.2 µs | 9.4 µs | -12.21% |
| ⚡ | Simulation | random_i16[0.95] |
95.6 µs | 77.5 µs | +23.39% |
Tip
Investigate this regression by commenting @codspeedbot fix this regression on this PR, or directly use the CodSpeed MCP with your agent.
Comparing claude/tpcds-slt-plans (ab68187) with develop (8e2aa05)
Footnotes
-
218 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports. ↩
a8ed1a2 to
9e66771
Compare
|
CI status on the previous head (
Generated by Claude Code |
9e66771 to
75f5a90
Compare
75f5a90 to
d5aed64
Compare
Mirror the TPC-H and ClickBench SLT layout for TPC-DS at scale factor 0.1: `slt/tpcds/generate_data.sh` generates the 24 tables with DuckDB's tpcds extension, exports them to Parquet, converts each to Vortex, and runs `duckdb/parity.slt`, which reads every table in both formats through DuckDB and fails if any row differs. The wrapper `slt/generate_data.sh` accepts `tpcds` like the other datasets. Each engine gets `results/q1` to `results/q99` and `plans/q1` to `plans/q99` from the upstream queries in `vortex-bench/sql/tpcds`, run unchanged. `tpcds.slt` asserts results and EXPLAIN plans against Vortex, and `parquet.slt` reruns the same result records against Parquet so both formats must agree. All 99 queries run on both engines. The runner treats TPC-DS like the other generated-data suites: its tests are ignored until both fixture formats exist. Signed-off-by: Joe Isaacs <joe.isaacs@live.co.uk> Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01L57FHoJ15heJVNaqgRq7xB
DuckDB's common-subplan optimizer keys a scan on its serialized form. The Vortex table function keeps pushed-down filters, projections and aggregates in its FFI bind data, which has no serializer, so two scans of the same file with different pushed-down filters serialized identically and were merged into one shared CTE, handing one branch the other's rows. Parquet is unaffected because its filters live in `table_filters`, which are serialized. Setting `verify_serialization = false` is how DuckDB expects a function with opaque bind data to opt out of plan serialization, and therefore of subplan merging. This is what TPC-DS q28 hits: its six quantity buckets all returned the fifth bucket's average. `slt/duckdb/common_subplan_pushdown.slt` is a smaller regression test over one file, and fails without this change with the second branch reporting the first branch's average. The TPC-H q11 DuckDB plan is regenerated: its scalar subquery is no longer folded into a shared CTE, so the plan gains the scans it used to read back through `CTE_SCAN`. Results are unchanged. Signed-off-by: Joe Isaacs <joe.isaacs@live.co.uk> Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01L57FHoJ15heJVNaqgRq7xB
d5aed64 to
ab68187
Compare
Summary
Follow-up to #9794 (ClickBench): the same SLT layout for TPC-DS at scale factor 0.1.
It also carries the DuckDB scan-merging fix that #9803 ended up not landing. Without it the DuckDB TPC-DS suite returns wrong results for q28, which is why CI was red here.
Changes
slt/tpcds/generate_data.shgenerates the 24 tables with DuckDB'stpcdsextension throughuvx, exports them to Parquet, converts each to Vortex withvx convert, and then runsduckdb/parity.slt, which reads every table in both formats through DuckDB and fails if any row differs.slt/generate_data.shacceptstpcdslike the other datasets; CI already calls the wrapper.create.slt.no,drop.slt.no,results/q1..q99.slt.noandplans/q1..q99.slt.nofrom the upstream queries invortex-bench/sql/tpcds, run unchanged.tpcds.sltasserts results and EXPLAIN plans (EXPLAIN (FORMAT json)withexplain_output = 'all'on DuckDB) against Vortex;parquet.sltreruns the same result records against Parquet so both formats must agree. All 99 queries run on both engines with no errors, and no tie-breaking edits to the queries were needed.Fixture size: 14MB, of which 12MB is the DuckDB JSON plans (the format the TPC-H PR chose).
The DuckDB scan-merging fix
DuckDB's common-subplan optimizer keys a scan on its serialized form. The Vortex table function keeps pushed-down filters, projections and aggregates in its FFI bind data, which has no serializer, so two scans of the same file with different pushed-down filters serialized identically and were merged into one shared CTE, handing one branch the other's rows. Parquet is unaffected because its filters live in
table_filters, which are serialized. Settingverify_serialization = falseis how DuckDB expects a function with opaque bind data to opt out of plan serialization, and therefore of subplan merging.TPC-DS q28 is the case in point: its six quantity buckets all returned the fifth bucket's average.
slt/duckdb/common_subplan_pushdown.sltis a smaller regression test over a single file; without the fix its second branch reports the first branch's average.The TPC-H q11 DuckDB plan is regenerated as a consequence: its scalar subquery is no longer folded into a shared CTE, so the plan gains the scans it previously read back through
CTE_SCAN. TheCTEandCTE_SCANnodes disappear, no cardinality estimate changes value, and q11's results are unchanged.Checks
cargo nextest run -p vortex-sqllogictestwith TPC-H, TPC-DS and ClickBench fixtures present: TPC-DS passes on both engines, and the new regression test passes.105 455became105 105), so it does catch the bug.clang-format --dry-run --Werroron the changed C++ file.One local test,
tpch/datafusion/tpch.slt, fails in this working copy only: its plans pinfile_groupspartition counts, and the local.vortexfixtures predate the onpair 0.2.1 compression change, so the files split into a different number of groups. CI regenerates fixtures from scratch and that test passed there on the previous head.🤖 Generated with Claude Code
https://claude.ai/code/session_01L57FHoJ15heJVNaqgRq7xB