2010YOUY01 commented on PR #25688:
URL: https://github.com/apache/datafusion/pull/25688#issuecomment-5965009472

   Here is what I understand from the latest discussion and code diff. I used 
AI to help summarize it, so please point out anything I misunderstood.
   
   The latest change keeps the existing physical optimizer rule order, but 
introduces one hard boundary through the `PhysicalAnalyzer` / 
`PhysicalOptimizer` split.
   
   Conceptually:
   
   - **Before the boundary:** there are no enforced repartition/sort operators 
yet, so rules are relatively free to transform the plan.
   - **After the boundary:** repartition/sort operators may already exist, so 
every later rule must recognize and preserve the distribution and ordering 
requirements that have already been satisfied.
   
   My major suggestion is to make this boundary mechanism **extensible**, 
instead of encoding one specific boundary through the Analyzer/Optimizer split.
   
   ```text
   # Current design
   
   PhysicalAnalyzer:
       OutputRequirements(add)
       aggregate_statistics
       join_selection
       LimitedDistinctAggregation
       FilterPushdown
       WindowTopN
       EnsureRequirements
   
       # Boundary:
       # distribution and ordering requirements are satisfied
   
   PhysicalOptimizer:
       ...remaining existing rules...
   
   
   # What I mean by extensible boundaries
   
   rule1
   rule2
   rule3
   
       # Boundary A:
       # distribution and ordering requirements are now enforced
   
   rule4
   rule5
   
       # Boundary B:
       # another optimizer invariant is now established
   
   rule6
   rule7
   ```
   
   If these boundaries can be represented explicitly, I think optimizer 
maintenance becomes much easier. Rules can clearly see which assumptions they 
are allowed to rely on, instead of those assumptions being hidden in rule 
ordering and implementation details.
   
   Projection pushdown is one concrete example of where another boundary could 
be useful. The important part is not this specific invariant, but that the same 
mechanism could express it naturally:
   
   ```text
   rule1
   
       # Before this point, projection has one canonical representation:
       #
       # ProjectionExec
       # -- child
   
   ProjectionPushDown
   
       # After this point, projection may either stay explicit:
       #
       # ProjectionExec(c1 + c2)
       # -- Join(output = [c1, c2])
       #
       # or be fused into an operator that supports it:
       #
       # Join(
       #     output = [c1, c2],
       #     projection = [c1],
       # )
   
   rule2
   rule3
   ```
   
   I suspect there are more hidden invariants like this in the optimizer today, 
so I think it is important that the mechanism can naturally support multiple 
boundaries rather than only this one distribution/ordering boundary.
   
   One additional nice-to-have is validation. I don't think this needs to be a 
major design decision, since it seems relatively easy to extend once boundaries 
are represented explicitly.
   
   For example, after a boundary establishes an invariant, we could validate it 
after every subsequent rule, at least in tests or debug builds:
   
   ```text
   EnsureRequirements
   
   Rule3
   ValidateEnsureRequirements
   
   Rule4
   ValidateEnsureRequirements
   ```
   
   That would make it much easier to identify exactly which rule first breaks 
the invariant, rather than discovering the violation only after the entire 
optimizer finishes.


-- 
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