[ 
https://issues.apache.org/jira/browse/IMPALA-15312?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=18108787#comment-18108787
 ] 

Aleksandr Efimov commented on IMPALA-15312:
-------------------------------------------

Numbers from a production deployment, in case they help justify printing a 
figure rather than just "(from HBO)".

Setup: 14-executor cluster, HBO enabled cluster-wide, in-memory cache backend. 
One BI-generated report measured twice, once with use_hbo_stats=false and once 
with true. 515 plan nodes, 3.2 GB scanned, 240 nodes carrying "(from HBO)". The 
report is 30 UNION branches over the same subplan shape, so those 515 nodes 
collapse to only 12 distinct estimate pairs - worth knowing before reading the 
spread as 515 independent samples.

Estimate accuracy, q-error = max(actual/estimate, estimate/actual) per node, 
taken from ExecSummary:

{noformat}
                       median      p90      max   over  under  exact
  use_hbo_stats=false   340.7   8592.1   8592.1    455      0     60
  use_hbo_stats=true      1.0      1.0     29.0      4      0    511
{noformat}

Est(on) / Est(off) per node, all 12 distinct pairs:

{noformat}
   150x         18 ->     14     ratio 0.78
    90x      4,770 ->     14     ratio 0.0029
    90x    120,290 ->     14     ratio 0.00012
    30x    120,290 ->  4,090     ratio 0.034
    30x  3,320,000 ->  6,780     ratio 0.0020
    30x     66,770 ->    111     ratio 0.0017
    30x     66,770 ->      1     ratio 0.000015
    30x          1 ->    111     ratio 111
    30x          1 ->      1     ratio 1
     2x      4,720 ->    406     ratio 0.086
     2x        337 ->    337     ratio 1
     1x    143,070 ->    420     ratio 0.0029
{noformat}

The estimate moved on 483 of 515 nodes although only 240 were substituted 
directly, so roughly half the effect is propagation up the tree.

Now the part that argues for this issue rather than for the annotation itself. 
The plan also changed: all 60 outer joins went from RIGHT OUTER to LEFT OUTER, 
because {{isInvertedJoinCheaper()}} reads both children's cardinalities and the 
substitution flips its answer. Its formula on the two sides, 18 rows of 36B 
against an aggregate of 30B rows:

{noformat}
  without HBO   rhs 4,770 rows   cost 2,913,126   inverted 1,128,057  -> invert
  with HBO      rhs    14 rows   cost    11,345   inverted    13,406  -> leave
{noformat}

Those are totalCost and invertedTotalCost. The code compares them after 
dividing by each side's {{getNumNodes()}}, and we did not establish those two 
values: {{invertJoins()}} runs on the single-node plan, before distribution, so 
the "hosts=" printed in the distributed plan is not necessarily what the check 
saw. The arithmetic reproduces the observed flip when both sides have the same 
node count, and is meant to illustrate the mechanism rather than to replay the 
planner's decision exactly.

What makes this worth an issue rather than a footnote: the counts of BROADCAST 
versus PARTITIONED are identical between the two plans, as is every other 
operator count. Reading the profiles with both estimates in hand, we concluded 
the plan had not changed at all, and only a per-node operator diff showed 
otherwise. So "original estimate" and "ratio" tell an operator that the 
estimate moved, but not whether the decision moved, and the second is the 
question they actually have.

A trap for anyone building that diff. Plan node ids do not move when a join 
flips: they are handed out as nodes are constructed, before {{invertJoins()}} 
runs, and {{invertJoin()}} keeps the id. Exchange ids do move - 
{{createHashJoinFragment()}} numbers the left child's exchange before the right 
child's, so an inversion swaps the two, and the merge aggregation takes the 
next id from the same counter. A naive per-id comparison reported 240 
differences of which 60 were real; the rest were exchanges and aggregations 
swapping places in the numbering. Comparing the whole-plan operator histogram 
separates them.

Profile size, measured by counting "(from HBO)" lines on a build without the 
annotation patch: 240 extra lines is +5.4% of the Plan section and +0.04% of 
the profile, about 21 KiB on 28 MB. Not a legibility concern at this scale.

> Show when an HBO cardinality changed a plan decision
> ----------------------------------------------------
>
>                 Key: IMPALA-15312
>                 URL: https://issues.apache.org/jira/browse/IMPALA-15312
>             Project: IMPALA
>          Issue Type: Improvement
>          Components: Frontend
>            Reporter: Aleksandr Efimov
>            Assignee: Aleksandr Efimov
>            Priority: Major
>
> h3. Problem
> IMPALA-15236 puts the provenance of an HBO cardinality next to the number: 
> the canonicalization strategy that matched, the hash key, the estimate the 
> planner had computed on its own, and the ratio between the two. That answers 
> where the number came from. It does not answer whether the number changed the 
> plan.
> The two questions come apart. Decisions that consume cardinalities are cost 
> based, so a corrected estimate can flip one while leaving the shape of the 
> plan alone. Join inversion is the clearest case: {{Planner.invertJoins()}} 
> inverts a join when {{isInvertedJoinCheaper()}} says so, and that check is a 
> function of the two children's cardinality and average row size. Correct the 
> build side and the verdict can flip, so a join that was planned inverted goes 
> back. The number of joins does not change, the broadcast/partitioned mix does 
> not change, and the operator histogram of the plan does not change - only the 
> side each join builds on.
> This is not hypothetical. On an outer-join-heavy query, HBO correcting a 
> build-side aggregate from a few thousand rows down to fourteen turned sixty 
> joins back from RIGHT OUTER to LEFT OUTER, and a comparison of the two plans 
> by operator counts reported them as the same plan.
> Answering "what did HBO do to this plan" today means running the query twice, 
> once with {{use_hbo_stats=false}}, and diffing the two plans. On a report 
> that runs for minutes that is a measurement exercise rather than debugging.
> h3. Proposed change
> Mark the nodes where the HBO substitution changed a planner decision, not 
> only the estimate, in the plan and in the profile.
> Two directions, each with a cost worth weighing:
> * Plan twice under a debug query option and diff the results. Exact, and only 
> paid for when someone asks for it.
> * Carry the pre-HBO estimate through the cardinality computation and 
> re-evaluate the cost based decisions with it. No second planning pass, but it 
> has to propagate: a node whose own key did not match can still get a 
> different cardinality because a descendant matched, and 
> {{PlanNode.cardinalityBeforeHbo_}} stays -1 on such a node, so a check that 
> reads only that field reports no change where there was one.
> h3. Note for the comparison itself
> Plan node ids are handed out as nodes are constructed, before 
> {{invertJoins()}} runs, and exchange nodes are numbered afterwards by the 
> distributed planner. Two plans of the same query built from different 
> estimates need not agree on ids, so a diff keyed on node id can report 
> differences that are only numbering.



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to