better-duck-core against the community
duckdb crate across three groups: primitive types, composite
types, and common end-to-end operations. The honest summary: better-duck-core leads on type
handling (notably UUID and the temporal types) and offers a safe composite-type appender the
duckdb crate lacks, while the two are close on raw operation throughput.
Methodology
How the numbers were produced. Latency columns are min / median / p95 over the measured reps
(warmup discarded). Throughput is
item_count / median_latency. Each library vendors its own
copy of DuckDB and the two cannot be linked into one process, so each ran in its own process.
The timings are still directly comparable — both are in-process, native calls with no
subprocess-per-operation overhead on either side.Test system
Test system
- CPU: Intel Core Ultra 7 155U (12 physical cores)
- RAM: ~15.5 GB
- Toolchain:
rustc 1.96.0(the project MSRV) - Compared against the
duckdbcrate, each vendoring its own DuckDB build
Primitive types
Insert + full-scan of 20,000 rows per type. better-duck-core is ahead on most primitive types, and substantially faster on a few — notablyUUID (≈50.95 ms vs ≈185.80 ms median), TIMESTAMPTZ
(≈50.47 ms vs ≈87.89 ms), and TIMESTAMP (≈47.30 ms vs ≈78.29 ms). The two are close on HUGEINT,
UHUGEINT, and DECIMAL.
Primitive types — latency (lower is better)
Primitive types — throughput (higher is better)
Composite types
Insert + full-scan of 2,000 rows ofLIST, ARRAY, STRUCT, and MAP, using each library’s
appender API.
The takeaway is a capability, not a speed result: better-duck-core offers a safe
appender path for LIST / ARRAY / STRUCT / MAP where the duckdb crate
offers none. Treat the composite charts as “better-duck-core has this capability.”
Composite types — latency (duckdb crate is a placeholder, see warning above)
Composite types — throughput (duckdb crate is a placeholder, see warning above)
Operations
A mix of end-to-end workloads. These results are mixed and reported faithfully: theduckdb crate is
somewhat faster on these particular operations, while better-duck-core stays competitive.
Operations — latency (lower is better)
Operations — throughput (higher is better)
Reading the results
- Type handling is better-duck-core’s strength — especially
UUIDand the temporal types, where it is multiples faster, and the safe composite-type appender theduckdbcrate lacks entirely. - Raw operations are close, with the
duckdbcrate marginally ahead on the simple CRUD / prepared-reuse paths measured here. - Pick the crate that fits your workload and the API surface you want — the appender, columnar reads, UDFs, async/pooling, and Arrow/Polars interop are all part of better-duck-core’s surface.
Choosing an API
Match the crate and API surface to your task.
Core crate
The driver API measured here.