The row checksum
Each row is reduced to a single 48-bit signed integer:- Columns are cast to text and joined with
|before hashing, in the order the comparison resolved them.NULLbecomes the sentinel<NULL>, so a null and an empty string are distinguishable. - Only 48 of the 128 bits are kept. That leaves room to sum millions of row checksums inside a 64-bit integer without overflowing, which is the whole trick — the aggregate is computed by the database, not by us.
- Subtracting 2^47 centres the values around zero, so a sum over many rows drifts towards zero rather than towards the top of the range.
HASHBYTES on SQL Server, STANDARD_HASH on Oracle, MD5 plus a base conversion elsewhere — so two different platforms produce the same number for the same data. Which hash function is used is negotiated per reconciliation.
What leaves the database, in full: one row per query containing a count and a sum. No row values, no keys, no column contents. That is true of the quick check and of every level of the drill-down, unless you explicitly raise the privacy level.
The quick check
One query per side:The bisection drill-down
When the totals disagree, the run needs to find where. It does that by splitting the key space and re-asking the same question of each piece.1
Split the key range into N segments
bisection.factor (default 32, maximum 1024) sets N. The boundaries come from the segmentation strategy below.2
Compare every segment in one query per side
Not N queries — one. The counts and checksums for all N segments come back from a single bucketed aggregate per side, so a level costs two queries regardless of the factor.
3
Recurse into the segments that differ; ignore the ones that agree
A segment whose count and checksum match on both sides is identical and is never queried again.
4
Stop at the threshold
Drilling stops when a segment’s row count falls below
bisection.threshold (default 16384), when --depth is reached, or when the segment cannot be split any further. Those segments are the run’s mismatch leaves.Segmentation strategies
How the key space is divided is configurable, and the choice is a trade-off between drill efficiency and what the boundaries reveal.When to choose something other than the default
- hash — sensitive keys
- time — time-partitioned tables
Privacy levels
By default nothing but counts and checksums is retrieved.reporting.level opts into more, per reconciliation:
detailed additionally requires consent_acknowledged: true — a deliberate speed bump, because it is the one setting that puts row values into a run record.
Cost, in queries
What each query scans depends on your schema, which is why key column indexing matters more than any setting on this page. Running locally covers the pre-run scan estimate and the gate flags.
Next
Comparison modes
Choosing between counts, checksums and aggregate measures.
Investigating results
Reading a segment tree and following a leaf to the rows.