Skip to content

Accuracy: guarantees for comparisons and top-k bands over estimates (#669 follow-up) #743

Open

Description

@zzylol

Problem, by example

rate(http_requests_total[5m]) > scalar(quantile(0.99, rate(http_request_duration_seconds[5m])))

The threshold is a KLL estimate of the p99, with rank error ε = 0.01. A series whose rate lies between the true p99 and the estimated p99 can be kept when it should be dropped, or dropped when it should be kept. The planner has no rule for what this means for the result: Stage 1 keeps the summary candidate, and the result's guarantee is None. So Stage 3 cannot check the entry's AccuracyTarget against it, and an approximate plan for this query can never be accepted as meeting a target.

The same applies to topk(k, …) over approximate values: an item whose true value is within the error band of the k-th value can be swapped in or out. No guarantee describes that band either.

Cause

Guarantee composition (crates/logical-asap-optimization/src/accuracy/composition.rs) covers arithmetic, folds and max/min (#687, #712). The leftovers listed in #687's limitations were never tracked:

  1. comparison guarantees (>, <, bool, filters by an estimate) and the top-k band;
  2. rank-interval guarantees (a quantile estimate as a rank interval rather than a value);
  3. nested operand-domain operations, for example a quotient of quotients;
  4. a constant-weight Count-Min norm (stream_row_count) has no binding statistic.

Proposal

  • For a comparison against an estimate with absolute error ε: the result is exact for rows whose value is farther than ε from the threshold. The guarantee says "membership exact outside a band of width 2ε" (at failure probability δ). Top-k gets the same band around the k-th value.
  • Express it as a new guarantee kind next to the value-error kinds, so Stage 3 can check it when the target asks for membership accuracy, and keeps None otherwise.
  • Items 2–4 each get a rule or an explicit "no guarantee" with a test.

Scope and acceptance

Related

Follow-up of #669 (closed: parts a and b merged in #687 and #712). #689, #711, #580.

Activity

  1. zzylol commented on Oct 29, 2026

    @zzylol
    ContributorAuthor

    New evidence for item 4 (a constant-weight Count-Min norm, stream_row_count, has no binding statistic), measured on main 61ee27f30.

    Example. count by (job)(a) + count by (job)(a) with --max-error 0.01 --failure-probability 0.001 --accuracy-metric absolute --enforce-accuracy-guarantees --series-count 10000 --sample-interval-ms 15000. Pass 1 offers Cms(depth=7 width=272) and Cms(depth=17 width=272). Every CMS plan is rejected with an unbound bound:

    accuracy_target_missed: q0: the output guarantees a Absolute { scale: None } bound None, failure probability Some(0.0004139937718785167), which misses target AccuracyTarget { accuracy_metric: Some(Absolute { scale: None }), max_error: 0.01, … }

    Declaring stream_norms: {"l1": 10000} on source a does not change this. The run with the declaration reports the same bound None in all 12 accuracy_target_missed rejections.

    Cause. The count's CMS weight is the constant 1. So operand_guarantee → stream_norm (crates/logical-asap-optimization/src/per_computation_candidates.rs:2555-2606) picks StreamNorm::ConstantWeight, and additive_as_absolute (accuracy/composition.rs:526-572) turns the bound into (e/w) · 1 · stream_row_count[a]. Stage 3's workload_statistic (crates/plan-selection/src/lib.rs:2739-2775) binds stream_l1_norm[…] and stream_l2_norm[…] through parse_source_norm_statistic, which knows only those two norms (composition.rs:66-75). No code binds stream_row_count[…], so the bound stays None even though the run knows the row count: the scan reads 10000 samples, from series_count × window / sample_interval.

    Two related observations from the same runs:

    • For the single query count by (job)(a) with --accuracy-metric absolute, the root guarantee is not converted at all. The CMS plan is rejected with "guarantees a Absolute { scale: Some(StreamL1) } bound Some(0.009993683192864136) … misses target … Absolute { scale: None }": a metric mismatch, not an unbound norm.
    • Even with the norm bound, this CMS cannot meet this target. Pass 1 sizes a count's CMS against ε as a fraction of the L1 norm (realization.rs:81-83, sizing_target), so width 272 gives about 0.01 × 10000 ≈ 100 in absolute terms, against a target of 0.01. Binding stream_row_count mainly turns None into a real number that the target can be compared with.

    Also, with --accuracy-metric absolute_stream_l1, the only rejections are compile errors. The CMS candidate fails with "node 2: invalid DAG: unsupported weighted frequency family". The UnivMon candidate fails with "node 3: … native output type differs from Planner output". So count by (job) never runs on a sketch today.

    Acceptance for item 4 (fails today). A plan-selection test where the bound of count by (job)(m) + count by (job)(m) evaluates to a number from the workload's series_count and sample_interval (or from a declared row-count fact), instead of None.

    Related: #1039 (budget split by reads; its count evidence depends on this), #1040 (the exact plan of that query does not compile), #727 (CountSketch count in the executor).

    🤖 Generated with Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    accuracyAccuracy requirements, guarantees, and propagationenhancementNew feature or requesterror-estimation

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions