Skip to main content

compara

Compare two tables on a composite key and get the counts, the per-column statistics and a self-contained HTML report. Key columns, compared columns and normalisation rules are parameters, so one tool serves every recurring comparison: a nightly export against yesterday's, a CSV against the Parquet a warehouse emits, a migration's source against its target.

  • Reads CSV, newline-delimited JSON and Parquet, and the two sides need not be in the same format.
  • Ten million rows × 20 columns in about a second on four cores (numbers below).
  • One static binary; the report is a single HTML file with nothing to host.
  • Exit codes made for pipelines: 0 identical, 1 differences, 2 error, 3 duplicate keys (with --fail-on-dups).

Install

Prebuilt binaries for Linux (x86_64, aarch64), macOS (arm64, x86_64) and Windows (x64) are on the releases page, and the same binaries through package managers:

Cargo cargo install --locked compara
npm npm install -g compara (or npx compara …)
pip / uv pip install compara · uv tool install compara
Homebrew brew install andrey-usa/tap/compara
Scoop scoop bucket add andrey-usa https://github.com/andrey-usa/scoop-bucket then scoop install compara

Use

compara compare a.csv b.csv -k account_id,txn_id -i updated_at
compara compare a.csv b.csv -k account_id,txn_id --trim --tolerance 0.005
compara compare export.csv warehouse.parquet -k id --summary
compara compare a.csv b.csv --profile orders --json summary.json --export-dir out/
compara columns data.parquet          # column names (reads only the footer)
compara head data.ndjson -n 5         # first rows, aligned

compare writes <a>__vs__<b>.html (or --out PATH): counts, per-column statistics, and the changed, added, removed and duplicate rows, each section capped at --max-rows (counts are always exact). examples/report.html is one, made from the two files next to it:

compara compare examples/orders_2026-08.csv examples/orders_2026-09.csv -k order_id,line_no -i updated_at
Option Effect
-k, --key composite key, required (or from a profile)
-c, --compare columns to diff; default every column present in both files except the key
-i, --ignore columns to skip (timestamps, run ids)
--trim, --ignore-case, --empty-is-null normalisation before comparing (applies to key and values)
--tolerance absolute numeric tolerance where both sides parse as numbers
--delimiter, --encoding override auto-detection (CSV only)
--threads how wide the default engine runs; the default is every core
--memory memory to plan for (e.g. 8G); decides when large files are joined in one pass instead of two
--max-rows rows embedded per report section (default 50 000)
--export-dir full, uncapped changed/added/removed CSVs
--json also write a JSON summary (counts and column stats; schema in docs/contract.schema.json)
--summary print the counts and write nothing
--engine auto (default), turbo, sortmerge or native
--no-compress plain JSON payload in the report, for pre-2023 browsers
--fail-on-dups exit 3 when either file has duplicate keys

Duplicate keys are counted and listed per file; the first occurrence of each key takes part in the join.

Profiles. A compara.toml in the working directory (or ~/.config/compara/compara.toml, or --config PATH) names recurring comparisons: key, compared and ignored columns, normalisation, engine. See compara.example.toml. The command line overrides the profile.

Speed

Ten million rows × 20 columns, keyed on (account_id, txn_id), --ignore updated_at, one GitHub Actions runner (AMD EPYC 7763, 4 vCPU / 16 GB), best of five (run 36672430118). Each cell is wall time · CPU time · memory above the mapped input.

Format Input a side compara
CSV 3,509 MB 1.20 s · 4.0 s · 591 MB
ndjson 8,487 MB 2.79 s · 10.4 s · 592 MB
Parquet 2,074 MB 1.41 s · 4.7 s · 1,342 MB

compara started as the Rust port in data-comparison-polyglot, where the same comparison is implemented in C, C++, Rust and Zig and measured side by side; that repository has the full tables and how they are produced.

Engines

Three backends, one result contract: every engine returns identical counts and column statistics for the same input, and the test suite asserts it cell for cell. --engine auto takes the first one that can load the input, in this order.

Engine Implementation Memory model Use it for
turbo mapped file, byte-level index; CSV, JSON and Parquet off-heap bytes, index in memory the default, and the fastest
sortmerge external sort, merge join bounded memory, spills to disk files past what memory can index
native over the csv crate in-memory, row-oriented the dependency-light baseline

All three read values as text, with no type inference, so 1.0 and 1 stay different unless a tolerance is set, and all three treat an empty field as absent whether or not it is quoted.

Input formats

turbo decides what a file is by its content rather than its name: a Parquet magic number, a leading {, or a CSV header.

Format How it is read
CSV mapped, scanned eight bytes at a time; a field is an offset and a length
newline-delimited JSON the same, addressed by key rather than by column number; \uXXXX is decoded, so an escaped and a literal character compare equal
Parquet pages decoded into an arena; dictionary-encoded columns point at the dictionary entry, so a repeated value costs eight bytes a row

The Parquet reader is written here rather than taken from a crate, to keep that representation instead of converting to Arrow arrays. It reads PLAIN, dictionary (PLAIN_DICTIONARY, RLE_DICTIONARY), RLE booleans and the version-2 delta encodings; uncompressed, snappy, gzip, zstd and LZ4-raw pages; data pages v1 and v2; definition levels for optional columns. It refuses, by name, nested or repeated schemas, BYTE_STREAM_SPLIT, LZO and Brotli.

A typed Parquet value is rendered to text by a fixed rule: byte arrays as their bytes, booleans true/false, integers and decimals in full, floats in the shortest round-trip form, dates YYYY-MM-DD, timestamps ISO 8601. tests/fixtures/formats/typed.csv is that rule written down.

Contributing

See CONTRIBUTING.md.

License

MIT

Metadata

Release files for compara 0.5.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Built distributions (wheels)

Table of built distributions (wheels) for compara 0.5.0
File
compara-0.5.0-py3-none-win_amd64.whl Python 3 none Windows x86-64 Details
compara-0.5.0-py3-none-manylinux_2_28_x86_64.whl Python 3 none Linux glibc 2.28+ x86-64 Details
compara-0.5.0-py3-none-manylinux_2_28_aarch64.whl Python 3 none Linux glibc 2.28+ ARM64 Details
compara-0.5.0-py3-none-macosx_11_0_arm64.whl Python 3 none macOS 11.0+ ARM64 Details
compara-0.5.0-py3-none-macosx_10_12_x86_64.whl Python 3 none macOS 10.12+ x86-64 Details

Total release size: 4.6 MB

Release files / compara-0.5.0-py3-none-win_amd64.whl

Download URL compara-0.5.0-py3-none-win_amd64.whl
Size 842.9 kB
Tags Python 3 Windows x86-64
SHA-256 checksum
How to use checksums
2a030a71d7c45bd7fe3b89cf9e1bb38f220b9c99705b452d0262a0088a110260
BLAKE2b-256 checksum
How to use checksums
896e93ed4d9934ec5d6cb7598b45b3d9bbb5754ff920ab5b4c1086da1aa8d431
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 10, 2026.

Transparency log

Release files / compara-0.5.0-py3-none-manylinux_2_28_x86_64.whl

Download URL compara-0.5.0-py3-none-manylinux_2_28_x86_64.whl
Size 961.7 kB
Tags Linux glibc 2.28+ x86-64 Python 3
SHA-256 checksum
How to use checksums
1a44bb6e42e2b84338ac2628c33bade1d23fa403d18547444f4a189c1603582d
BLAKE2b-256 checksum
How to use checksums
74cc96f8dad3bf751f702adebb35e4e66b85e39acb292e68b5c33e4a0b40d400
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 10, 2026.

Transparency log

Release files / compara-0.5.0-py3-none-manylinux_2_28_aarch64.whl

Download URL compara-0.5.0-py3-none-manylinux_2_28_aarch64.whl
Size 871.1 kB
Tags Linux glibc 2.28+ ARM64 Python 3
SHA-256 checksum
How to use checksums
80f2f468e9448ad0dd5febccfde3a45f02e50bef3c67872264735cad53c40cf8
BLAKE2b-256 checksum
How to use checksums
19e24cfc14d9003f5b8596e8addd49e6fec8cf14f781849b11aca86c4466517f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 10, 2026.

Transparency log

Release files / compara-0.5.0-py3-none-macosx_11_0_arm64.whl

Download URL compara-0.5.0-py3-none-macosx_11_0_arm64.whl
Size 900.5 kB
Tags Python 3 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
3b967b80ca08720c211670e3705229ac54dc9310e8c2fdcf2fdd45e60391ccdf
BLAKE2b-256 checksum
How to use checksums
a25a3a88dc6c08026db6161fd0e745ab821dfea73962f76f7a7374d60430ab04
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 10, 2026.

Transparency log

Release files / compara-0.5.0-py3-none-macosx_10_12_x86_64.whl

Download URL compara-0.5.0-py3-none-macosx_10_12_x86_64.whl
Size 996.8 kB
Tags Python 3 macOS 10.12+ x86-64
SHA-256 checksum
How to use checksums
44919e143879c8bed1799569e50ca237f151065518267f66a2de07108d8886e1
BLAKE2b-256 checksum
How to use checksums
5100db1f8c739c1ef1f96edc9ae45bc0fb055c0c00e67016af1f6d9c2667e7e1
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 10, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.5.0 This release

5 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page