Skip to content

Arithmetic over an approximate quantile has no accuracy guarantee, so with guarantees enforced the ratio-of-quantiles query plans only exact (1 of 49 Pass 1 DAGs valid) #1034

Open

Description

@zzylol

Problem, by example

Workload tools/dag-viewer/memo-examples/promql/ratio-of-quantiles-5m.json: one query every minute, with ε = 0.01, δ = 0.001 and no metric set.

avg by (job) (quantile_over_time(0.5, data[5m]) / quantile_over_time(0.5, data[5m]) + quantile_over_time(0.9, data[5m]))

Measured on main (f49900b) with guarantees enforced and every Pass 1 DAG costed:

stage_pipeline --workload tools/dag-viewer/memo-examples/promql/ratio-of-quantiles-5m.json \
  --deployment-capabilities '{"raw_data_retained":true,"query_time_results_retained":false}' \
  --cost-model aws-fargate-us-east-1 --enforce-accuracy-guarantees --price-enumerated 49 --out ratio.json
Pass 1 DAGs Valid Rejected
49 (7 quantile 0.5 candidates × 7 quantile 0.9 candidates) 1: the all-exact one 48, all with no_accuracy_guarantee

Every DAG that uses a sketch (KLL or DDSketch) for either quantile is rejected:

Q1: the output has no guarantee, and the deployment has no evidence for it, so it cannot meet target AccuracyTarget { accuracy_metric: None, max_error: 0.01, failure_probability: Some(0.001), accuracy_scope: WholeResult }

In DAG E2 (KLL for quantile 0.9, the rest exact), the guarantee is lost at the +:

Node Guarantee
q0.5 / q0.5 (BinaryOp Div, exact operands) exact
quantile 0.9 (SummaryEstimate, KLL) rank error, KLL
… + q0.9 (BinaryOp Add) none
avg by (job) and the root none

So with guarantees enforced, any query that does arithmetic on an approximate quantile can only be planned exact. Without enforcement, the same search picks sketch plans freely: 169 of 169 Pass 2 DAGs were valid, and the selected plan cost 78.93/s against 237.63/s for the exact plan (#1004 measurements).

Why

arithmetic_guarantee (crates/logical-asap-optimization/src/per_computation_candidates.rs:2735) composes value errors only. Its doc says so: "a relative error shifted by a constant or added to another, a rank error … has none".

  • A rank error (KLL) says nothing about how far the returned value is from the true quantile's value. Adding it to another value gives no bound.
  • A relative error (DDSketch) added to another value has no closed-form bound either.
  • operand_domain_statistic already leaves products and quotients of value errors symbolic, so that Stage 3 can bind them from declared source facts. Rank errors are excluded ("an operand's error has no value form").

This is sound behaviour, not a wrong result. It does mean the planner never uses a sketch for these queries.

Options

  1. Keep as is, and say so. Document in planner-layering.md that arithmetic over a rank or relative error has no guarantee, so such queries plan exact under enforcement. The viewer already shows the rejection reason per enumerated DAG.
  2. Relative + value, through declared bounds. Leave x + y with a relative-error x symbolic on |x|'s upper bound, as operand_domain_statistic does for products. Stage 3 then binds the bound from declared source facts (for example a declared value range). This covers DDSketch.
  3. Rank → value, through a declared distribution fact. Turn a rank error ε into a value error using a declared bound on the value distribution (for example the largest gap between the values at ranks q ± ε), then compose as an absolute error. This covers KLL, but needs a new source fact.

Recommendation: (1) now, since it costs nothing and is correct. (2) after that, since it reuses the existing symbolic-statistic path. (3) only with a workload that needs it.

Scope and acceptance

  • For (1): the doc paragraph, plus a test that the ratio workload under --enforce-accuracy-guarantees selects the all-exact plan with the 48 no_accuracy_guarantee rejections.
  • For (2): a unit test in per_computation_candidates.rs where DDSketch q0.9 + exact gets a symbolic absolute bound, and a stage-pipeline test where declaring the value bound makes a DDSketch DAG valid on this workload.

Related

Activity

  1. zzylol commented on Oct 29, 2026

    @zzylol
    ContributorAuthor

    More evidence, with a rank target this time (main 61ee27f30, --max-error 0.01 --failure-probability 0.001 --accuracy-metric rank --enforce-accuracy-guarantees --series-count 10000 --sample-interval-ms 15000):

    Query Rejections Selected
    quantile_over_time(0.5, a[5m]) none KLL, 0.000350/s
    quantile_over_time(0.5, a[5m]) - quantile_over_time(0.5, a[5m]) 10 × no_accuracy_guarantee exact, 0.000403/s
    quantile_over_time(0.99, a[5m]) - quantile_over_time(0.5, a[5m]) 126 × no_accuracy_guarantee exact, 0.000514/s

    The memo offers half-budget sketches for the two-quantile difference: Kll(failure_probability=0.0005 k=746), Kll(… k=1184) and DDSketch(alpha=0.004962809790010847) at budget_share 2. But none can be used, because the difference has no guarantee:

    no_accuracy_guarantee: q0: the output has no guarantee, and the deployment has no evidence for it, so it cannot meet target AccuracyTarget { accuracy_metric: Some(Rank), max_error: 0.01, failure_probability: Some(0.001), accuracy_scope: WholeResult }

    From the code, this is intended, not a missing rule. arithmetic_guarantee (per_computation_candidates.rs:2728-2729) gives no guarantee to "a rank error" under arithmetic. metric_meets (accuracy/mod.rs:55-69) says that "a rank error has no distribution-free value error". A rank target on q0.99 − q0.5 is also not well defined: the difference is a value, not a rank, so no rank-error bound applies to it. A rank target on a difference can only be met by exact. The useful path is still options 2 and 3 here: state the target in value terms, and turn the rank error into a value error from a declared distribution fact.

    So this adds a data point for option (1), documenting it: a rank target on arithmetic over quantiles always plans exact. The stage viewer shows only no_accuracy_guarantee, which does not tell the user that the target metric is the reason.

    🤖 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