github-actions[bot] commented on code in PR #66898:
URL: https://github.com/apache/doris/pull/66898#discussion_r4257049079


##########
fe/fe-core/src/main/java/org/apache/doris/nereids/rules/rewrite/RewriteCteChildren.java:
##########
@@ -82,6 +82,14 @@ public Plan visit(Plan plan, CascadesContext context) {
     @Override
     public Plan visitLogicalCTEAnchor(LogicalCTEAnchor<? extends Plan, ? 
extends Plan> cteAnchor,
             CascadesContext cascadesContext) {
+        // Derive the operative slots of the producer before the statistics of 
the consumer are
+        // derived below: StatsCalculator.computeOlapScan fetches the column 
stats of the slots that
+        // are marked as operative, and without this derivation every column 
of every scan of the
+        // producer would be fetched. The derived producer is the plan whose 
statistics are derived
+        // and which is rewritten below, so that those statistics are not 
computed on a discarded
+        // copy of it.
+        Plan derivedProducer = cteAnchor.child(0).accept(
+                new OperativeColumnDerive(), new 
OperativeColumnDerive.DeriveContext());

Review Comment:
   [P2] Include consumer keys in the producer derivation
   
   A retained CTE can have this reduced tree (for example, `WITH c AS (SELECT a 
FROM wide) SELECT a FROM c INTERSECT SELECT a FROM c`):
   
   ```text
   CTEAnchor(c)
     Producer -> Project(a#p) -> Scan(wide[a#p,b,...])
     Intersect DISTINCT
       Consumer(a#c1 -> a#p)
       Consumer(a#c2 -> a#p)
   ```
   
   The new context is empty, the producer has no expressions, and the 
forwarding project adds no demand, so `a#p` is marked non-operative. The 
prerequisite `StatsDerive` therefore only probes its cache entry; on a miss it 
never requests the analyzed key statistics. Consumer derivation copies that 
UNKNOWN value, and marking `a#c1`/`a#c2` in the outer pass cannot reach `a#p` 
because there is no CTE demand mapping. `InferSetOperatorDistinct` then skips 
local DISTINCT inference, before the producer is rewritten at line 124. A warm 
cache can mask this. Please seed/map consumer estimation keys into the producer 
context (or conservatively retain producer outputs for this prerequisite pass) 
and cover the materialized-CTE load requests. This is distinct from the 
existing late-CTE-pass thread: the pass now runs early enough but omits 
downstream keys.



##########
fe/fe-core/src/main/java/org/apache/doris/nereids/jobs/executor/Rewriter.java:
##########
@@ -589,6 +596,15 @@ public class Rewriter extends AbstractBatchJobExecutor {
                         bottomUp(new EliminateNotNull()),
                         topDown(new ConvertInnerOrCrossJoin())
                 ),
+                // InferSetOperatorDistinct in the next topic is the first 
rewrite rule that derives
+                // statistics: it calls StatsDerive on a set operation whose 
statistics are missing,
+                // and StatsCalculator.computeOlapScan fetches the column 
stats of the operative
+                // slots only. Derive them before that rule, so that this 
consumer and every later one
+                // does not fall back to fetching the stats of all table 
columns of a scan. The
+                // derivation is repeated once more before "Reorder join 
before eager aggregation"
+                // and at the end of rewrite, where the operative slots of the 
plans that reach the
+                // memo are computed.
+                custom(RuleType.OPERATIVE_COLUMN_DERIVE, 
OperativeColumnDerive::new),

Review Comment:
   [P2] Derive UNION DISTINCT deduplication keys before the stats consumer
   
   This new pass also sees the pre-lowering tree:
   
   ```text
   ResultSink(u.a)
     Union DISTINCT(u.a)
       Project(a#1) -> Scan(wide1[a#1,b,...])
       Project(a#2) -> Scan(wide2[a#2,b,...])
   ```
   
   `OperativeColumnDerive.visitLogicalUnion` only propagates parent demands and 
never treats DISTINCT outputs as operative; sinks and forwarding projects add 
none. Both scans are therefore marked derived-empty. On absent cache entries, 
the following `InferSetOperatorDistinct` obtains UNKNOWN key NDVs through 
cache-only probes and declines local deduplication, without requesting the 
statistics it needs. `BuildAggForUnion` adds group-key demand only afterwards, 
too late to redo that choice. This affects ordinary `SELECT a FROM wide1 UNION 
SELECT a FROM wide2`; a warm cache can mask it. Please seed all DISTINCT union 
keys before the early pass and add direct UNION DISTINCT versus UNION ALL 
planner/load-request coverage. This is distinct from the existing 
pass-placement thread: the placement is fixed, but the union visitor does not 
handle this earlier DISTINCT shape.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


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

Reply via email to