Skip to content

sql: stabilize decimal SQRDIFF with large offsets - #174680

Open
Alignyx wants to merge 1 commit into
cockroachdb:masterfrom
Alignyx:fix-173065-decimal-sqrdiff-precision
Open

sql: stabilize decimal SQRDIFF with large offsets#174680
Alignyx wants to merge 1 commit into
cockroachdb:masterfrom
Alignyx:fix-173065-decimal-sqrdiff-precision

Conversation

@Alignyx

@Alignyx Alignyx commented Sep 4, 2026

Copy link
Copy Markdown

Fixes #173065.

Summary

SQRDIFF on high-precision DECIMAL inputs with a large common offset could
return a negative value. The magnitude depended on how many local aggregation
states the physical plan created, so equivalent distributed scan and join plans
could produce different answers.

This change keeps the existing Welford aggregation and distributed intermediate
state, but performs the calculation in coordinates centered around a stable
offset. It also adds focused coverage for local accumulation, final partial-state
merging, and SQL execution with forced DistSQL.

Root cause

The decimal aggregate uses tree.IntermediateCtx, whose precision is 25
significant digits. For the reported value
99999999999999999999.9999999999, the first local Welford update previously
proceeded as follows:

  1. value - 0 was rounded to 25 significant digits while computing delta.
  2. The running mean was set to that rounded value.
  3. Subtracting the rounded mean from the original input left a residual of
    -1E-10.
  4. Multiplying that residual by a delta of approximately 1E20 stored
    -1E10 in the sum of squared differences.

The bad state was therefore created by the first local input, before partial
aggregation state was serialized. Each local aggregation state contributed one
such error, which explains why the distributed scan and lateral join plans in
the issue returned different negative multiples of 1E10.

The final decimal SQRDIFF aggregate had a related precision problem. It derived
each partial mean as sum / count in IntermediateCtx and then subtracted the
independently rounded means. Two large partial means separated only in digits
beyond that context could become indistinguishable. For example, merging two
singleton states whose values differ by 1E-10 returned zero instead of the
correct 5E-21.

Clamping a negative result to zero would hide the corrupted state and would
also be incorrect for inputs with a small, positive variance. Ten copies of the
reported value plus one value smaller by 2000 should produce
3636363.6363636363636, whereas the old implementation returned a negative
result.

Fix

The local decimal accumulator now saves the first non-NULL input as an offset
and feeds value - offset into the existing Welford recurrence. Variance and
SQRDIFF are invariant under translation, so this preserves the result while
making the required precision depend on the spread of the inputs instead of
their absolute magnitude.

The final accumulator similarly chooses the first partial mean as a common
offset. For each partial state it computes

centeredSum = sum - offset * count

using tree.ExactCtx, and only then divides by the count in
IntermediateCtx. This retains low-order differences that would be lost by
subtracting separately rounded large means. The existing parallel Welford merge
then operates on those centered means.

The distributed (sqrdiff, sum, count) intermediate representation, aggregate
signatures, planner mappings, result rounding, float implementation, and integer
delegation are unchanged. The additional decimal fields are included in memory
accounting and reset with the rest of the accumulator state.

Testing

Added TestDecimalSqrDiffLargeOffset, covering:

  • a large singleton, whose SQRDIFF must be zero;
  • the positive-variance case with a large common offset;
  • final aggregation of two singleton partial states separated by 1E-10.

Added the regression_173065 SQL logic test with forced DistSQL, covering both
identical large values and the positive-variance case.

Validation included:

  • the complete //pkg/sql/sem/builtins:builtins_test target;
  • the regression across 12 local, fakedist, tenant, and mixed-version logic-test
    configurations;
  • the complete aggregate logic test under local and fakedist configurations;
  • the complete five-node distsql_agg logic suite;
  • repeated three-node executions of the reported distributed scan and lateral
    merge-join plans.

After the change, the reported all-equal inputs return zero in every tested plan,
while the positive-variance case retains its nonzero result.

Release note (bug fix): Fixed SQRDIFF, VARIANCE, and standard-deviation
aggregates returning negative or plan-dependent results for high-precision
DECIMAL values with a large common offset.

Decimal SQRDIFF rounded a large initial value while updating its Welford mean, then multiplied the rounded residual by the original-scale delta. Distributed plans accumulated one such error per partial aggregation state.

Center local inputs around the first value. During final aggregation, center each exact partial sum around one common offset before deriving its mean. This preserves translation-invariant differences without changing the distributed aggregate interface.

Fixes cockroachdb#173065

Release note (bug fix): Fixed SQRDIFF, VARIANCE, and standard-deviation aggregates returning negative or plan-dependent results for high-precision DECIMAL values with a large common offset.
@Alignyx
Alignyx requested a review from a team as a code owner September 4, 2026 12:21
@Alignyx
Alignyx requested review from bghal and removed request for a team September 4, 2026 12:21
@blathers-crl

blathers-crl Bot commented Sep 4, 2026

Copy link
Copy Markdown

Thank you for contributing to CockroachDB. Please ensure you have followed the guidelines for creating a PR.

My owl senses detect your PR is good for review. Please keep an eye out for any test failures in CI.

🦉 Hoot! I am a Blathers, a bot for CockroachDB. My owner is dev-inf.

@blathers-crl blathers-crl Bot added the O-community Originated from the community label Sep 4, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

O-community Originated from the community

Projects

None yet

Development

Successfully merging this pull request may close these issues.

sql: SQRDIFF function returns negative value for large DECIMAL when all values are equal, with magnitude varying by execution plan

1 participant