pratham76 commented on code in PR #58656:
URL: https://github.com/apache/spark/pull/58656#discussion_r4148301436


##########
sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/optimizer/subquery.scala:
##########
@@ -158,20 +159,23 @@ object RewritePredicateSubquery extends Rule[LogicalPlan] 
with PredicateHelper {
       // Filter the plan by applying left semi and left anti joins.
       withSubquery.foldLeft(newFilter) {
         case (p, Exists(sub, _, _, conditions, subHint)) =>
-          val (joinCond, outerPlan) = rewriteExistentialExpr(conditions, p)
-          val join = buildJoin(outerPlan, 
rewriteDomainJoinsIfPresent(outerPlan, sub, joinCond),
+          val (joinCond, outerPlan, newSub) =
+            rewriteExistentialExprInJoinCondition(conditions, p, sub)
+          val join = buildJoin(outerPlan, 
rewriteDomainJoinsIfPresent(outerPlan, newSub, joinCond),
             LeftSemi, joinCond, subHint)
           Project(p.output, join)
         case (p, Not(Exists(sub, _, _, conditions, subHint))) =>
-          val (joinCond, outerPlan) = rewriteExistentialExpr(conditions, p)
-          val join = buildJoin(outerPlan, 
rewriteDomainJoinsIfPresent(outerPlan, sub, joinCond),
+          val (joinCond, outerPlan, newSub) =
+            rewriteExistentialExprInJoinCondition(conditions, p, sub)
+          val join = buildJoin(outerPlan, 
rewriteDomainJoinsIfPresent(outerPlan, newSub, joinCond),
             LeftAnti, joinCond, subHint)
           Project(p.output, join)
         case (p, InSubquery(values, ListQuery(sub, _, _, _, conditions, 
subHint))) =>
           // Deduplicate conflicting attributes if any.
-          val newSub = dedupSubqueryOnSelfJoin(p, sub, Some(values))
-          val inConditions = values.zip(newSub.output).map(EqualTo.tupled)
-          val (joinCond, outerPlan) = rewriteExistentialExpr(inConditions ++ 
conditions, p)
+          val dedupSub = dedupSubqueryOnSelfJoin(p, sub, Some(values))
+          val inConditions = values.zip(dedupSub.output).map(EqualTo.tupled)
+          val (joinCond, outerPlan, newSub) =
+            rewriteExistentialExprInJoinCondition(inConditions ++ conditions, 
p, dedupSub)

Review Comment:
   The premise checks out. `SizeInBytesOnlyStatsPlanVisitor.visitJoin` gives 
`LeftAnti | LeftSemi` an
   explicit left-preserving estimate and falls through to `default(p)` for 
everything else, so an
   `ExistenceJoin` gets the generic product estimate even though it emits 
exactly one row per left row
   with one Boolean appended. `JoinEstimation` has no `ExistenceJoin` case 
either.
   
   Two things I would like to settle before changing it, though.
   
   It is not introduced here. `visitJoin` returns `p.left.stats` for 
`LeftSemi`, so an existence join
   built on the outer plan — where every nested subquery went before this PR — 
already propagated its
   inflated estimate through the enclosing semi join. This PR changes which 
side carries it, which is
   the side broadcast eligibility is decided on, so the consequence you 
describe is new even though the
   misestimate is not.
   
   And the fix reaches further than this rule. Eight approved TPC-DS plans 
contain an `ExistenceJoin`
   (q10, q35, q45 and their sf100 variants), so correcting the estimate in 
either statistics mode can
   change those plans, and the golden files would have to be regenerated and 
reviewed. That is a
   different kind of change from the routing fix, in a different component, 
with its own suites
   (`JoinEstimationSuite`, `BasicStatsEstimationSuite`) and its own risk of 
moving estimates for plans
   that are fine today.
   
   Given that, I would rather do it as a separate JIRA, with your success 
criteria carried over
   verbatim: a left-derived size in the size-only visitor that includes the 
appended Boolean width, an
   explicit left-preserving estimate with left-side attribute statistics in the 
CBO estimator, and a
   regression pinning that an `ExistenceJoin`-wrapped build side stays 
broadcast-eligible. Please do let know if that is acceptable? Thanks!



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