Try Opteryx

Benchmarking

Be Aware

Benchmarks deserve scepticism, including ours. Every suite below encodes an opinion about which workloads matter, and none of them is your workload. We run them to find our own blind spots, not to produce a number to quote.

Opteryx is measured continuously against two kinds of suite: correctness harnesses that check the engine returns the right answer, and performance harnesses that check how long it takes. Both matter, in that order — performance work on incorrect behaviour is wasted effort.

This page describes what is run and how. It deliberately publishes no timings. Numbers from a benchmark are only meaningful with the hardware, the build, and the date attached, and a documentation page is a poor place to keep all three current. Where results are published, this page says where to find them.


Correctness suites

Suite Command What it checks
Shape battery make q The core regression suite: every query returns the expected row count, column count, and error type.
Full test suite make test Unit, integration, planner, connector, and type tests, with optimizer plan validation on.
sqllogictest make slt Portable, engine-agnostic SQL correctness — see below.
Fuzzing make fuzz Generated and metamorphic queries. CI runs a short pass on every push; a 100,000-iteration run goes nightly.

sqllogictest

sqllogictest is the correctness harness from SQLite: a portable, language-agnostic file format of SQL statements and expected results. Opteryx runs it through an external-engine driver against a fork of the runner, in three tiers:

Tier Command Assertion
Shapes make slt-shapes The result has the expected shape and types.
Results make slt-results The result values match exactly.
Run-only make slt-run-only The statement executes without error; no result assertion.

The tiers exist because not every query has a portable expected result. Splitting them means a query whose values are engine-specific can still be pinned on shape, rather than being dropped from the suite entirely.

Most performance benchmarks assert nothing about output — they time a query and move on. sqllogictest is what verifies the answers, which is why it is the first suite listed and not an afterthought to the timing ones.

Differential testing against DuckDB

Where the SQL standard leaves behaviour implementation-defined, "correct" needs a reference. Opteryx uses DuckDB as that reference: the same query, the same data, and a comparison of the results. Where the two disagree and Opteryx is deliberately different — byte-oriented strings being the main one — the divergence is documented in SQL Compatibility Notes rather than silently tolerated.


Performance suites

Each suite is a make target in the engine repository. All of them except signals compare against a stored DuckDB baseline.

Suite Command Shape What it stresses
TPC-H make tpch 22 queries, SF1 by default Join planning, predicate handling, subqueries, plan stability. Small data, demanding query shapes.
ClickBench make clickbench 43 queries over the hits web-analytics dataset Single-table scan, filter, and aggregation at scale. Where performance cliffs show up first.
JOB make job 113 queries over 21 IMDB tables Join enumeration, cardinality estimation, statistics coverage. The suite that punishes a bad cost model.
H2O db-benchmark make h2o 10 group-by + 5 join queries Aggregation and join throughput on the suite other engines publish against.
JSONBench make jsonbench 5 queries over a Bluesky NDJSON dump Nested-JSON reading and -> / ->> extraction through READ_JSONL.
Medicare1 make medicare1 10 queries over a public healthcare dataset Wide tables, string-heavy grouping.
OData dashboard make dash 37 query shapes taken from the hosted OData service's query log Real dashboard-shaped queries, as opposed to benchmark-shaped ones.
Signals make signals Synthetic security-findings dataset Customer-shaped queries against a dataset that only exists in the repo. No DuckDB baseline.

Why so many? Because each one catches a different class of failure. TPC-H and ClickBench barely exercise join ordering, which is the whole point of JOB. JOB says nothing about JSON reading. A suite that only ever ran ClickBench would optimise for scans and let the optimizer rot. The benchmarks blog post covers the reasoning and what each suite found when it was first run.

RISC-V

RISC-V Support carries the one set of published pass/fail results and indicative timings on this site — a point-in-time bring-up snapshot on a specific single-board computer, explicitly not a benchmark claim.


Method

The runners share a common approach, and the details matter when reading a result:

  • Warm, multi-iteration. Each query runs several times (three by default) and the best time is the one compared. The first iteration is normally the slowest — caches are cold and file footers have not been read.
  • Fresh session per iteration. Each run opens its own session and drains the result to morsels without rendering anything, so the number reflects the engine rather than the table formatter.
  • Timeouts are recorded, not fatal. A query that exceeds its per-query timeout is logged as a timeout and the suite continues. A suite that aborts on the first slow query tells you nothing about the other 42.
  • Matched allocator. The benchmark targets preload the same allocator the production build uses, so a local run and a deployed run are measuring the same thing.
  • Every run is kept. Per-iteration results are written to results/<git-sha>-<timestamp>.csv in the suite's own directory, so a regression can be bisected against the commit that caused it.

Baselines

The DuckDB baseline is not regenerated on every run — it lives in a JSON file alongside each suite and is refreshed deliberately with a separate calibration target (make tpch-bench-duckdb, make clickbench-duckdb, make job-duckdb, and so on). Two reasons: re-measuring the reference on every run would make every comparison a comparison against a moving target, and calibrating on the machine you are benchmarking on is what makes the ratio meaningful at all.

That last point is the important caveat. A ratio is only comparable to another ratio measured on the same machine, with the same baseline. Absolute millisecond figures from one developer's laptop say nothing about anyone else's.

What the numbers are not

  • Not audited. No third party has verified any of these runs.
  • Not a service level. There is no performance guarantee. Opteryx is pre-1.0 and still being tuned hard, so an optimizer change that helps most queries can slow an individual one.
  • Not a claim of parity. Several suites currently exist precisely because Opteryx is behind on them; that gap is the point of running them.

Reproducing results

Opteryx's ClickBench configuration is published in the ClickBench repository, so the run can be reproduced independently rather than taken on trust. The suites themselves live in the engine repository under tests/performance/, each with its own data fetcher — make jsonbench-data, make medicare1-fetch, and the per-suite fetch_data.py scripts.


TPC, TPC Benchmark, and TPC-H are trademarks of the Transaction Processing Performance Council. ClickHouse is a registered trademark of ClickHouse, Inc.