Right answers first. Speed, measured.
A vectorised executor runs verified plans over typed columns. Five TPC-H queries return the same answers as DuckDB, decimals exact. They are 11×–46× slower than DuckDB on one thread, down from 137–1 408×, and the 3× gate is still missed. This page says how far and why.
Progress across phases, seconds per query
TPC-H SF 0.1 on the shared development host, 3 CPUs / 6 GB; indicative, not a production promise, 21–22 Oct 2026
Batches, typed columns, verified plans
The executor runs the plan the verifier accepted. Every optimisation below was checked against a reference interpreter before it was kept.
Vectorised operators
Filter, hash join and aggregate run on column batches rather than row by row. Expressions, comparisons and decimal arithmetic evaluate over whole columns.
BuiltTyped columns
Decimals are typed 128-bit integer columns with a scale; group keys are typed. No per-value boxing in the hot path.
BuiltBatch aggregation
GROUP BY with count, sum, avg, min and max aggregates a batch at a time. Digit counting and typed group keys came in the same phase as columnar storage.
BuiltProjection pruning
The scan decodes only the columns the plan can observe, straight into column builders. The bare lineitem scan went from 2.92 s to 0.57 s (5.1×) with this alone.
BuiltAnswers equal DuckDB
Decimals compared exactly, averages within a relative 1e-9. Five queries, every phase, every run: equal.
BuiltPlanning cost
Verify, optimise, re-verify: 1–8 ms per query, catalog load under 0.1 ms. Planning is not where the time goes.
BuiltWhere the time went, and where it still goes
Each phase was profiled before it was planned. The measurements below are from the dated reports; the host is a shared development server, so the numbers are indicative.
Seconds per query, TPC-H SF 0.1, median of three including planning
Answers equal DuckDB's in every row
| Phase | Date | What changed | Q1 | Q6 | Q10 |
|---|---|---|---|---|---|
| P2c | 21 Oct | First run: plans verified and optimised as the node does, over full security chains. Profile: decoding whole rows took 49% of a scan, turning rows into columns 24%, the storage layer 6%. | 4.278 | 3.269 | 3.536 |
| P2d | 21 Oct | Projected scans and typed decimals: decode only observed columns, no whole-row re-encode. Scan 5.1× faster; queries 1.9–3.5×. | 2.3 | 1.258 | 1.162 |
| P2e | 21 Oct | Vectorised expressions and batch aggregation. Queries 3.7–6.1× faster than before P2d; what remained was reading the row store. | 1.165 | 0.537 | 0.777 |
| P3c | 22 Oct | Columnar collections: per-column chunks, read only observed columns. Columnar 2.5–7.3× faster than row storage; 11–46× DuckDB on one thread. | 0.308 | 0.074 | 0.245 |
Overall: Q6 3.269 s to 0.074 s and Q1 4.278 s to 0.308 s in three phases; the report puts the range at 10×–44× faster with answers always equal.
The remaining gap, in four parts
From the 22 Oct report: reading two columns of lineitem's row groups takes about 15 ms, so what is left is the executor
- Per-row validity vectors. Null handling is still tracked row by row inside batches.
- Row-at-a-time joins and group keys. Hash joins and group keys are built one row at a time.
- No SIMD. Kernels are plain loops; the specification calls for SIMD filters, hashing and distance kernels.
- A single thread. DuckDB's one-thread figure is the fair comparison today; parallel reads at a snapshot are a later phase.
The 3× gate. Phase 2 asked for the TPC-H subset within 3× of DuckDB on one node. It was not met: 137–1 408× on 21 Oct. The decision record accepts the phase on correctness, keeps the 3× goal, and measures it again at each step on a dedicated benchmark host, never on the development server.
Checked before it is timed
Every executor change ships with the same campaign. Speed numbers are published only after it is clean.
See the comparison in full.
The DuckDB page carries the whole table, the methodology and what DuckDB does better.
