cloud-fan commented on code in PR #58631:
URL: https://github.com/apache/spark/pull/58631#discussion_r4000377527


##########
sql/catalyst/src/main/scala/org/apache/spark/sql/internal/SQLConf.scala:
##########
@@ -7366,15 +7366,34 @@ object SQLConf {
   val OPTIMIZE_NULL_AWARE_ANTI_JOIN =
     buildConf("spark.sql.optimizeNullAwareAntiJoin")
       .internal()
-      .doc("When true, NULL-aware anti join execution will be planed into " +
+      .doc("When true, NULL-aware anti join execution can be planned as " +
         "BroadcastHashJoinExec with flag isNullAwareAntiJoin enabled, " +
         "optimized from O(M*N) calculation into O(M) calculation " +
         "using Hash lookup instead of Looping lookup. " +
-        "Only support for singleColumn NAAJ for now.")
+        "Only support for singleColumn NAAJ for now. The optimization is also 
controlled by " +
+        "spark.sql.optimizeNullAwareAntiJoin.broadcastThreshold.")
       .version("3.1.0")
       .booleanConf
       .createWithDefault(true)
 
+  val NULL_AWARE_ANTI_JOIN_BROADCAST_THRESHOLD =
+    buildConf("spark.sql.optimizeNullAwareAntiJoin.broadcastThreshold")

Review Comment:
   Thanks for raising this. I prefer to keep the current `-1` semantics. This 
threshold is not intended to follow `spark.sql.autoBroadcastJoinThreshold`: 
disabling the NAAJ optimization is already controlled by 
`spark.sql.optimizeNullAwareAntiJoin=false`, while this threshold needs an 
unbounded default to restore the original behavior. `Long.MaxValue` is not 
sufficient because `sizeInBytes` is a `BigInt`; the `threshold < 0` branch is 
genuinely unbounded and covers estimates above `Long.MaxValue`. 
`createOptional` would encode the same unbounded state as `None`, but would not 
improve correctness here. The config is internal and its documentation 
explicitly calls out the negative-value semantics, so I prefer to keep `-1`.



##########
sql/core/src/test/scala/org/apache/spark/sql/JoinSuite.scala:
##########
@@ -1410,6 +1365,50 @@ class JoinSuite extends SharedSparkSession with 
AdaptiveSparkPlanHelper
     }
   }
 
+  test("SPARK-36082: NAAJ hash join preserves floating-point equality") {
+    Seq(false, true).foreach { adaptiveEnabled =>

Review Comment:
   Fixed in 36a284541db. The test now calls `checkAnswer` first to execute the 
query, then collects from `queryExecution.executedPlan` through 
`AdaptiveSparkPlanHelper`, so the AQE-enabled cases verify that the final 
adaptive plan actually uses the null-aware broadcast hash join.



##########
sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/optimizer/joins.scala:
##########
@@ -498,9 +438,11 @@ trait JoinSelectionHelper extends Logging {
       getBroadcastBuildSide(join, hintOnly = true, conf).orElse {
         if (noShufflePlannedBefore) getBroadcastBuildSide(join, hintOnly = 
false, conf) else None
       }
-    case j if ExtractSingleColumnNullAwareAntiJoin.extract(j).isDefined =>
-      if (NullAwareAntiJoinPlanning.decide(j, conf) ==
-          NullAwareAntiJoinPlanning.BroadcastHash) {
+    // `JoinSelection` always builds from the right for this shape. A negative 
threshold preserves
+    // the original unbounded NAAJ behavior, while zero disables the broadcast 
hash optimization.
+    case j @ ExtractSingleColumnNullAwareAntiJoin(_, _) =>
+      val threshold = conf.nullAwareAntiJoinBroadcastThreshold
+      if (threshold < 0 || (threshold > 0 && j.right.stats.sizeInBytes <= 
threshold)) {

Review Comment:
   Fixed in 36a284541db. The positive-threshold path now also requires 
`rightSize >= 0`, and `JoinSelectionHelperSuite` covers a negative reported 
size.



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