You are viewing a plain text version of this content. The canonical link for it is here.
Posted to reviews@spark.apache.org by "WweiL (via GitHub)" <gi...@apache.org> on 2023/11/29 09:06:10 UTC

[PR] [DO-NOT-REVIEW][DRAFT] Spark 45637 multiple state test [spark]

WweiL opened a new pull request, #44076:
URL: https://github.com/apache/spark/pull/44076

   <!--
   Thanks for sending a pull request!  Here are some tips for you:
     1. If this is your first time, please read our contributor guidelines: https://spark.apache.org/contributing.html
     2. Ensure you have added or run the appropriate tests for your PR: https://spark.apache.org/developer-tools.html
     3. If the PR is unfinished, add '[WIP]' in your PR title, e.g., '[WIP][SPARK-XXXX] Your PR title ...'.
     4. Be sure to keep the PR description updated to reflect all changes.
     5. Please write your PR title to summarize what this PR proposes.
     6. If possible, provide a concise example to reproduce the issue for a faster review.
     7. If you want to add a new configuration, please read the guideline first for naming configurations in
        'core/src/main/scala/org/apache/spark/internal/config/ConfigEntry.scala'.
     8. If you want to add or modify an error type or message, please read the guideline first in
        'core/src/main/resources/error/README.md'.
   -->
   
   ### What changes were proposed in this pull request?
   <!--
   Please clarify what changes you are proposing. The purpose of this section is to outline the changes and how this PR fixes the issue. 
   If possible, please consider writing useful notes for better and faster reviews in your PR. See the examples below.
     1. If you refactor some codes with changing classes, showing the class hierarchy will help reviewers.
     2. If you fix some SQL features, you can provide some references of other DBMSes.
     3. If there is design documentation, please add the link.
     4. If there is a discussion in the mailing list, please add the link.
   -->
   logs:
   ```
    
   -=-=-=-=-=-=-=
   currentBatchId = 0, lastExecutionRequiresAnotherBatch = false, isNewDataAvailable = true, shouldConstructNextBatch (with currbatchID) = true
   ===hash=== shouldRunAnotherBatch: true watermarkHasChanged: true newInputWatermark: 8000 eventTimeWatermarkForEviction: 0 stateWatermarkPredicates: state cleanup [ left key predicate: (input[0, struct<start:timestamp,end:timestamp>, false].end <= 0), right key predicate: (input[0, struct<start:timestamp,end:timestamp>, false].end <= 0) ]
   ===StateStoreSaveExec=== shouldRunAnotherBatch: true, newInputWM: 8000 wm evict: 0
   ===StateStoreSaveExec=== shouldRunAnotherBatch: true, newInputWM: 8000 wm evict: 0
    
   -=-=-=-=-=-=-=
   currentBatchId = 1, lastExecutionRequiresAnotherBatch = true, isNewDataAvailable = false, shouldConstructNextBatch (with currbatchID) = true
   ===StateStoreSaveExec=== remove key: [0,1000000018,0,0,4c4b40]value:[0,1800000018,5,0,0,4c4b40]
   ===hash=== shouldRunAnotherBatch: false watermarkHasChanged: false newInputWatermark: 8000 eventTimeWatermarkForEviction: 8000 stateWatermarkPredicates: state cleanup [ left key predicate: (input[0, struct<start:timestamp,end:timestamp>, false].end <= 8000000), right key predicate: (input[0, struct<start:timestamp,end:timestamp>, false].end <= 8000000) ]
   ===StateStoreSaveExec=== shouldRunAnotherBatch: false, newInputWM: 8000 wm evict: 8000
   ===StateStoreSaveExec=== shouldRunAnotherBatch: false, newInputWM: 0 wm evict: 8000
    
   -=-=-=-=-=-=-=
   
   currentBatchId = 2, lastExecutionRequiresAnotherBatch = false, isNewDataAvailable = false, shouldConstructNextBatch (with currbatchID) = false
   ===hash=== shouldRunAnotherBatch: false watermarkHasChanged: false newInputWatermark: 8000 eventTimeWatermarkForEviction: 8000 stateWatermarkPredicates: state cleanup [ left key predicate: (input[0, struct<start:timestamp,end:timestamp>, false].end <= 8000000), right key predicate: (input[0, struct<start:timestamp,end:timestamp>, false].end <= 8000000) ]
   ===StateStoreSaveExec=== shouldRunAnotherBatch: false, newInputWM: 8000 wm evict: 8000
   ===StateStoreSaveExec=== shouldRunAnotherBatch: false, newInputWM: 0 wm evict: 8000
    
   -=-=-=-=-=-=-=
   
   currentBatchId = 2, lastExecutionRequiresAnotherBatch = false, isNewDataAvailable = false, shouldConstructNextBatch (with currbatchID) = false
   ===hash=== shouldRunAnotherBatch: false watermarkHasChanged: false newInputWatermark: 8000 eventTimeWatermarkForEviction: 8000 stateWatermarkPredicates: state cleanup [ left key predicate: (input[0, struct<start:timestamp,end:timestamp>, false].end <= 8000000), right key predicate: (input[0, struct<start:timestamp,end:timestamp>, false].end <= 8000000) ]
   ===StateStoreSaveExec=== shouldRunAnotherBatch: false, newInputWM: 8000 wm evict: 8000
   ===StateStoreSaveExec=== shouldRunAnotherBatch: false, newInputWM: 0 wm evict: 8000
    
   -=-=-=-=-=-=-=
   
   currentBatchId = 2, lastExecutionRequiresAnotherBatch = false, isNewDataAvailable = false, shouldConstructNextBatch (with currbatchID) = false
   ```
   
   ### Why are the changes needed?
   <!--
   Please clarify why the changes are needed. For instance,
     1. If you propose a new API, clarify the use case for a new API.
     2. If you fix a bug, you can clarify why it is a bug.
   -->
   
   
   ### Does this PR introduce _any_ user-facing change?
   <!--
   Note that it means *any* user-facing change including all aspects such as the documentation fix.
   If yes, please clarify the previous behavior and the change this PR proposes - provide the console output, description and/or an example to show the behavior difference if possible.
   If possible, please also clarify if this is a user-facing change compared to the released Spark versions or within the unreleased branches such as master.
   If no, write 'No'.
   -->
   
   
   ### How was this patch tested?
   <!--
   If tests were added, say they were added here. Please make sure to add some test cases that check the changes thoroughly including negative and positive cases if possible.
   If it was tested in a way different from regular unit tests, please clarify how you tested step by step, ideally copy and paste-able, so that other reviewers can test and check, and descendants can verify in the future.
   If tests were not added, please describe why they were not added and/or why it was difficult to add.
   If benchmark tests were added, please run the benchmarks in GitHub Actions for the consistent environment, and the instructions could accord to: https://spark.apache.org/developer-tools.html#github-workflow-benchmarks.
   -->
   
   
   ### Was this patch authored or co-authored using generative AI tooling?
   <!--
   If generative AI tooling has been used in the process of authoring this patch, please include the
   phrase: 'Generated-by: ' followed by the name of the tool and its version.
   If no, write 'No'.
   Please refer to the [ASF Generative Tooling Guidance](https://www.apache.org/legal/generative-tooling.html) for details.
   -->
   


-- 
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: reviews-unsubscribe@spark.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: reviews-unsubscribe@spark.apache.org
For additional commands, e-mail: reviews-help@spark.apache.org


Re: [PR] [DO-NOT-REVIEW][DRAFT] Spark 45637 multiple state test [spark]

Posted by "WweiL (via GitHub)" <gi...@apache.org>.
WweiL commented on code in PR #44076:
URL: https://github.com/apache/spark/pull/44076#discussion_r1411160900


##########
sql/core/src/main/scala/org/apache/spark/sql/execution/streaming/StreamingSymmetricHashJoinExec.scala:
##########
@@ -637,18 +653,22 @@ case class StreamingSymmetricHashJoinExec(
         thisRow: UnsafeRow,
         subIter: Iterator[InternalRow])
       extends CompletionIterator[InternalRow, Iterator[InternalRow]](subIter) {
-
+      // scalastyle:off
       private val iteratorNotEmpty: Boolean = super.hasNext
 
       override def completion(): Unit = {
         val isLeftSemiWithMatch =
           joinType == LeftSemi && joinSide == LeftSide && iteratorNotEmpty
         // Add to state store only if both removal predicates do not match,
         // and the row is not matched for left side of left semi join.
+        println(s"!stateKeyWatermarkPredicateFunc(key): ${!stateKeyWatermarkPredicateFunc(key)}" +
+          s" !stateValueWatermarkPredicateFunc(thisRow): ${!stateValueWatermarkPredicateFunc(thisRow)}")
         val shouldAddToState =
           !stateKeyWatermarkPredicateFunc(key) && !stateValueWatermarkPredicateFunc(thisRow) &&
           !isLeftSemiWithMatch
         if (shouldAddToState) {
+          println(s"wei==add to state: $thisRow")

Review Comment:
   So what happens here is in the no data batch, the wm of `stateKeyWatermarkPredicateFunc` is updated to the new global wm (8), the emitted key from both parent window aggregations are [0, 5). Hence `stateKeyWatermarkPredicateFunc(key)` returns true, meaning that the window should not be added to the join state store.
   
   This is wrong, because the two [0, 5) windows should be joined here. 
   
   This looks like some updates to the multiple state operators that we need to consider



-- 
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: reviews-unsubscribe@spark.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: reviews-unsubscribe@spark.apache.org
For additional commands, e-mail: reviews-help@spark.apache.org


Re: [PR] [DO-NOT-REVIEW][DRAFT] Spark 45637 multiple state test [spark]

Posted by "WweiL (via GitHub)" <gi...@apache.org>.
WweiL commented on code in PR #44076:
URL: https://github.com/apache/spark/pull/44076#discussion_r1409957775


##########
sql/core/src/main/scala/org/apache/spark/sql/execution/streaming/StreamingSymmetricHashJoinExec.scala:
##########
@@ -637,18 +653,22 @@ case class StreamingSymmetricHashJoinExec(
         thisRow: UnsafeRow,
         subIter: Iterator[InternalRow])
       extends CompletionIterator[InternalRow, Iterator[InternalRow]](subIter) {
-
+      // scalastyle:off
       private val iteratorNotEmpty: Boolean = super.hasNext
 
       override def completion(): Unit = {
         val isLeftSemiWithMatch =
           joinType == LeftSemi && joinSide == LeftSide && iteratorNotEmpty
         // Add to state store only if both removal predicates do not match,
         // and the row is not matched for left side of left semi join.
+        println(s"!stateKeyWatermarkPredicateFunc(key): ${!stateKeyWatermarkPredicateFunc(key)}" +
+          s" !stateValueWatermarkPredicateFunc(thisRow): ${!stateValueWatermarkPredicateFunc(thisRow)}")
         val shouldAddToState =
           !stateKeyWatermarkPredicateFunc(key) && !stateValueWatermarkPredicateFunc(thisRow) &&
           !isLeftSemiWithMatch
         if (shouldAddToState) {
+          println(s"wei==add to state: $thisRow")

Review Comment:
   If comment out the if (shoudAddToState) above, then there is data:
   ```
   [info] - SPARK-45637 window agg + window agg -> join on window, append mode *** FAILED *** (6 seconds, 953 milliseconds)
   [info]   == Results ==
   [info]   !== Correct Answer - 1 ==              == Spark Answer - 1 ==
   [info]   !struct<_1:int,_2:int,_3:int,_4:int>   struct<window:struct<start:timestamp,end:timestamp>,count:bigint,count:bigint>
   [info]   ![0,5,5,1]                             [[1969-12-31 16:00:00.0,1969-12-31 16:00:05.0],1,5]
   [info] 
   ```
   My [0, 5, 5, 1] answer is badly written but the idea is the same as the spark answer



-- 
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: reviews-unsubscribe@spark.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: reviews-unsubscribe@spark.apache.org
For additional commands, e-mail: reviews-help@spark.apache.org


Re: [PR] [DO-NOT-REVIEW][DRAFT] Spark 45637 multiple state test [spark]

Posted by "github-actions[bot] (via GitHub)" <gi...@apache.org>.
github-actions[bot] commented on PR #44076:
URL: https://github.com/apache/spark/pull/44076#issuecomment-2041662026

   We're closing this PR because it hasn't been updated in a while. This isn't a judgement on the merit of the PR in any way. It's just a way of keeping the PR queue manageable.
   If you'd like to revive this PR, please reopen it and ask a committer to remove the Stale tag!


-- 
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: reviews-unsubscribe@spark.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: reviews-unsubscribe@spark.apache.org
For additional commands, e-mail: reviews-help@spark.apache.org


Re: [PR] [DO-NOT-REVIEW][DRAFT] Spark 45637 multiple state test [spark]

Posted by "WweiL (via GitHub)" <gi...@apache.org>.
WweiL commented on code in PR #44076:
URL: https://github.com/apache/spark/pull/44076#discussion_r1408970548


##########
sql/core/src/test/scala/org/apache/spark/sql/streaming/MultiStatefulOperatorsSuite.scala:
##########
@@ -878,6 +878,147 @@ class MultiStatefulOperatorsSuite
     testOutputWatermarkInJoin(join3, input1, -40L * 1000 - 1)
   }
 
+  test("SPARK-45637 window agg + window agg -> join on window, append mode") {
+    val impressions = MemoryStream[Int]
+    val clicks = MemoryStream[Int]
+
+    val impressionsWithWatermark = impressions.toDF()
+      .withColumn("impressionTime", timestamp_seconds($"value"))
+      .withColumnRenamed("value", "impressionAdId")
+      .withWatermark("impressionTime", "0 seconds")
+
+    // clickTime is always later than impressionTime for clickAdId = impressionAdId
+    // Here we manually set the difference to 2 seconds (see the (Multi)AddData below)
+    val clicksWithWatermark = clicks.toDF()
+      .withColumn("timeSec", timestamp_seconds($"value"))
+      .selectExpr("value as clickAdId", "timeSec + INTERVAL 2 seconds as clickTime")
+      .withWatermark("clickTime", "0 seconds")
+
+    val clicksWindow = clicksWithWatermark.groupBy(
+      window($"clickTime", "5 seconds")
+    ).count()
+
+    val impressionsWindow = impressionsWithWatermark.groupBy(
+      window($"impressionTime", "5 seconds")
+    ).count()
+
+    val clicksAndImpressions = clicksWindow.join(impressionsWindow, "window", "inner")
+
+    withSQLConf((SQLConf.SHUFFLE_PARTITIONS.key, "1")) {
+      testStream(clicksAndImpressions)(
+        MultiAddData(
+          (impressions, Seq(0 to 8: _*)),
+          (clicks, Seq(6))
+        ),
+        // data batch triggered
+
+        // global watermark: (0, 0) [drop, evict]
+        // impression [impressionAdId, impressionTime]:
+        //    wm:     (0, 0)
+        //    input:  (0, 0), (1, 1), (2, 2), (3, 3), ..., (8, 8)
+        //    agg:    [0, 5) -> 5, [5, 10) -> 4
+        //    state:  [0, 5) -> 5, [5, 10) -> 4
+        //    output: None
+        // click [clickAdId, clickTime]
+        //    wm:     (0, 0)
+        //    input:  (6, 8)
+        //    agg:    [0, 5) -> 0, [5, 10) -> 1
+        //    state:  [0, 5) -> 0, [5, 10) -> 1
+        //    output: None
+        // join:
+        //    all None
+
+        // no-data batch triggered (shouldRunAnotherBatch)
+
+        // global watermark: (0, 8) (default is min across multiple watermarks)
+        // impression:
+        //    wm:     (0, 8)
+        //    input:  None
+        //    agg:    None
+        //    state:  [5, 10) -> 4
+        //    output: [0, 5) -> 5 (actually no, the state is not evicting any rows, why?)

Review Comment:
   why? logs see the description



-- 
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: reviews-unsubscribe@spark.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: reviews-unsubscribe@spark.apache.org
For additional commands, e-mail: reviews-help@spark.apache.org


Re: [PR] [DO-NOT-REVIEW][DRAFT] Spark 45637 multiple state test [spark]

Posted by "WweiL (via GitHub)" <gi...@apache.org>.
WweiL commented on code in PR #44076:
URL: https://github.com/apache/spark/pull/44076#discussion_r1437952915


##########
sql/core/src/test/scala/org/apache/spark/sql/streaming/MultiStatefulOperatorsSuite.scala:
##########
@@ -814,68 +814,183 @@ class MultiStatefulOperatorsSuite
     }
   }
 
-  test("stream-stream time interval join - output watermark for various intervals") {
-    def testOutputWatermarkInJoin(
-        df: DataFrame,
-        input: MemoryStream[(String, Timestamp)],
-        expectedOutputWatermark: Long): Unit = {
-      testStream(df)(
-        // dummy row to trigger execution
-        AddData(input, ("1", Timestamp.valueOf("2023-01-01 01:00:10"))),
-        CheckAnswer(),
-        Execute { query =>
-          val lastExecution = query.lastExecution
-          val joinOperator = lastExecution.executedPlan.collect {
-            case j: StreamingSymmetricHashJoinExec => j
-          }.head
+  test("SPARK-45637-1 join on window, append mode") {

Review Comment:
   The row is added in the first batch (not no-data batch) here



-- 
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: reviews-unsubscribe@spark.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: reviews-unsubscribe@spark.apache.org
For additional commands, e-mail: reviews-help@spark.apache.org


Re: [PR] [DO-NOT-REVIEW][DRAFT] Spark 45637 multiple state test [spark]

Posted by "WweiL (via GitHub)" <gi...@apache.org>.
WweiL commented on code in PR #44076:
URL: https://github.com/apache/spark/pull/44076#discussion_r1409958741


##########
sql/core/src/test/scala/org/apache/spark/sql/streaming/MultiStatefulOperatorsSuite.scala:
##########
@@ -814,68 +814,183 @@ class MultiStatefulOperatorsSuite
     }
   }
 
-  test("stream-stream time interval join - output watermark for various intervals") {
-    def testOutputWatermarkInJoin(
-        df: DataFrame,
-        input: MemoryStream[(String, Timestamp)],
-        expectedOutputWatermark: Long): Unit = {
-      testStream(df)(
-        // dummy row to trigger execution
-        AddData(input, ("1", Timestamp.valueOf("2023-01-01 01:00:10"))),
-        CheckAnswer(),
-        Execute { query =>
-          val lastExecution = query.lastExecution
-          val joinOperator = lastExecution.executedPlan.collect {
-            case j: StreamingSymmetricHashJoinExec => j
-          }.head
+  test("SPARK-45637-1 join on window, append mode") {
+    val impressions = MemoryStream[Int]
+    val clicks = MemoryStream[Int]
 
-          val outputWatermark = joinOperator.produceOutputWatermark(0)
-          assert(outputWatermark.get === expectedOutputWatermark)
-        }
+    val impressionsWithWatermark = impressions.toDF()
+      .withColumn("impressionTime", timestamp_seconds($"value"))
+      .withColumnRenamed("value", "impressionAdId")
+      .withWatermark("impressionTime", "0 seconds")
+
+    // clickTime is always later than impressionTime for clickAdId = impressionAdId
+    // Here we manually set the difference to 2 seconds (see the (Multi)AddData below)
+    val clicksWithWatermark = clicks.toDF()
+      .withColumn("timeSec", timestamp_seconds($"value"))
+      .selectExpr("value as clickAdId", "timeSec + INTERVAL 2 seconds as clickTime")
+      .withWatermark("clickTime", "0 seconds")
+
+    val clicksWindow = clicksWithWatermark.select(
+      window($"clickTime", "5 seconds")
+    )
+
+    val impressionsWindow = impressionsWithWatermark.select(
+      window($"impressionTime", "5 seconds")
+    )
+
+    val clicksAndImpressions = clicksWindow.join(impressionsWindow, "window", "inner")
+
+    withSQLConf((SQLConf.SHUFFLE_PARTITIONS.key, "1")) {
+      testStream(clicksAndImpressions)(
+        MultiAddData(
+          (impressions, Seq(0 to 8: _*)),
+          (clicks, Seq(1, 6))
+        ),
+        CheckAnswer((0, 5, 5, 1))
       )
     }
+  }
 
-    val input1 = MemoryStream[(String, Timestamp)]
-    val df1 = input1.toDF()
-      .selectExpr("_1 as leftId", "_2 as leftEventTime")
-      .withWatermark("leftEventTime", "5 minutes")
+  test("SPARK-45637 window agg + window agg -> join on window, append mode") {

Review Comment:
   This is the test ran



-- 
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: reviews-unsubscribe@spark.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: reviews-unsubscribe@spark.apache.org
For additional commands, e-mail: reviews-help@spark.apache.org


Re: [PR] [DO-NOT-REVIEW][DRAFT] Spark 45637 multiple state test [spark]

Posted by "WweiL (via GitHub)" <gi...@apache.org>.
WweiL commented on code in PR #44076:
URL: https://github.com/apache/spark/pull/44076#discussion_r1409957775


##########
sql/core/src/main/scala/org/apache/spark/sql/execution/streaming/StreamingSymmetricHashJoinExec.scala:
##########
@@ -637,18 +653,22 @@ case class StreamingSymmetricHashJoinExec(
         thisRow: UnsafeRow,
         subIter: Iterator[InternalRow])
       extends CompletionIterator[InternalRow, Iterator[InternalRow]](subIter) {
-
+      // scalastyle:off
       private val iteratorNotEmpty: Boolean = super.hasNext
 
       override def completion(): Unit = {
         val isLeftSemiWithMatch =
           joinType == LeftSemi && joinSide == LeftSide && iteratorNotEmpty
         // Add to state store only if both removal predicates do not match,
         // and the row is not matched for left side of left semi join.
+        println(s"!stateKeyWatermarkPredicateFunc(key): ${!stateKeyWatermarkPredicateFunc(key)}" +
+          s" !stateValueWatermarkPredicateFunc(thisRow): ${!stateValueWatermarkPredicateFunc(thisRow)}")
         val shouldAddToState =
           !stateKeyWatermarkPredicateFunc(key) && !stateValueWatermarkPredicateFunc(thisRow) &&
           !isLeftSemiWithMatch
         if (shouldAddToState) {
+          println(s"wei==add to state: $thisRow")

Review Comment:
   If comment out the if (shoudAddToState) above, then there is data:
   ```
   [info] - SPARK-45637 window agg + window agg -> join on window, append mode *** FAILED *** (6 seconds, 953 milliseconds)
   [info]   == Results ==
   [info]   !== Correct Answer - 1 ==              == Spark Answer - 1 ==
   [info]   !struct<_1:int,_2:int,_3:int,_4:int>   struct<window:struct<start:timestamp,end:timestamp>,count:bigint,count:bigint>
   [info]   ![0,5,5,1]                             [[1969-12-31 16:00:00.0,1969-12-31 16:00:05.0],1,5]
   [info] 
   ```
   My [0, 5, 5, 1] answer is badly formatted but it means the same as the spark answer



-- 
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: reviews-unsubscribe@spark.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: reviews-unsubscribe@spark.apache.org
For additional commands, e-mail: reviews-help@spark.apache.org


Re: [PR] [DO-NOT-REVIEW][DRAFT] Spark 45637 multiple state test [spark]

Posted by "WweiL (via GitHub)" <gi...@apache.org>.
WweiL commented on code in PR #44076:
URL: https://github.com/apache/spark/pull/44076#discussion_r1437953371


##########
sql/core/src/main/scala/org/apache/spark/sql/execution/streaming/StreamingSymmetricHashJoinExec.scala:
##########
@@ -637,18 +653,22 @@ case class StreamingSymmetricHashJoinExec(
         thisRow: UnsafeRow,
         subIter: Iterator[InternalRow])
       extends CompletionIterator[InternalRow, Iterator[InternalRow]](subIter) {
-
+      // scalastyle:off
       private val iteratorNotEmpty: Boolean = super.hasNext
 
       override def completion(): Unit = {
         val isLeftSemiWithMatch =
           joinType == LeftSemi && joinSide == LeftSide && iteratorNotEmpty
         // Add to state store only if both removal predicates do not match,
         // and the row is not matched for left side of left semi join.
+        println(s"!stateKeyWatermarkPredicateFunc(key): ${!stateKeyWatermarkPredicateFunc(key)}" +
+          s" !stateValueWatermarkPredicateFunc(thisRow): ${!stateValueWatermarkPredicateFunc(thisRow)}")
         val shouldAddToState =
           !stateKeyWatermarkPredicateFunc(key) && !stateValueWatermarkPredicateFunc(thisRow) &&
           !isLeftSemiWithMatch
         if (shouldAddToState) {
+          println(s"wei==add to state: $thisRow")

Review Comment:
   stateKeyWatermarkPredicateFunc's wm should be 0 here, not 8



-- 
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: reviews-unsubscribe@spark.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: reviews-unsubscribe@spark.apache.org
For additional commands, e-mail: reviews-help@spark.apache.org


Re: [PR] [DO-NOT-REVIEW][DRAFT] Spark 45637 multiple state test [spark]

Posted by "WweiL (via GitHub)" <gi...@apache.org>.
WweiL commented on code in PR #44076:
URL: https://github.com/apache/spark/pull/44076#discussion_r1408970548


##########
sql/core/src/test/scala/org/apache/spark/sql/streaming/MultiStatefulOperatorsSuite.scala:
##########
@@ -878,6 +878,147 @@ class MultiStatefulOperatorsSuite
     testOutputWatermarkInJoin(join3, input1, -40L * 1000 - 1)
   }
 
+  test("SPARK-45637 window agg + window agg -> join on window, append mode") {
+    val impressions = MemoryStream[Int]
+    val clicks = MemoryStream[Int]
+
+    val impressionsWithWatermark = impressions.toDF()
+      .withColumn("impressionTime", timestamp_seconds($"value"))
+      .withColumnRenamed("value", "impressionAdId")
+      .withWatermark("impressionTime", "0 seconds")
+
+    // clickTime is always later than impressionTime for clickAdId = impressionAdId
+    // Here we manually set the difference to 2 seconds (see the (Multi)AddData below)
+    val clicksWithWatermark = clicks.toDF()
+      .withColumn("timeSec", timestamp_seconds($"value"))
+      .selectExpr("value as clickAdId", "timeSec + INTERVAL 2 seconds as clickTime")
+      .withWatermark("clickTime", "0 seconds")
+
+    val clicksWindow = clicksWithWatermark.groupBy(
+      window($"clickTime", "5 seconds")
+    ).count()
+
+    val impressionsWindow = impressionsWithWatermark.groupBy(
+      window($"impressionTime", "5 seconds")
+    ).count()
+
+    val clicksAndImpressions = clicksWindow.join(impressionsWindow, "window", "inner")
+
+    withSQLConf((SQLConf.SHUFFLE_PARTITIONS.key, "1")) {
+      testStream(clicksAndImpressions)(
+        MultiAddData(
+          (impressions, Seq(0 to 8: _*)),
+          (clicks, Seq(6))
+        ),
+        // data batch triggered
+
+        // global watermark: (0, 0) [drop, evict]
+        // impression [impressionAdId, impressionTime]:
+        //    wm:     (0, 0)
+        //    input:  (0, 0), (1, 1), (2, 2), (3, 3), ..., (8, 8)
+        //    agg:    [0, 5) -> 5, [5, 10) -> 4
+        //    state:  [0, 5) -> 5, [5, 10) -> 4
+        //    output: None
+        // click [clickAdId, clickTime]
+        //    wm:     (0, 0)
+        //    input:  (6, 8)
+        //    agg:    [0, 5) -> 0, [5, 10) -> 1
+        //    state:  [0, 5) -> 0, [5, 10) -> 1
+        //    output: None
+        // join:
+        //    all None
+
+        // no-data batch triggered (shouldRunAnotherBatch)
+
+        // global watermark: (0, 8) (default is min across multiple watermarks)
+        // impression:
+        //    wm:     (0, 8)
+        //    input:  None
+        //    agg:    None
+        //    state:  [5, 10) -> 4
+        //    output: [0, 5) -> 5 (actually no, the state is not evicting any rows, why?)

Review Comment:
   why? logs see the description



-- 
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: reviews-unsubscribe@spark.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: reviews-unsubscribe@spark.apache.org
For additional commands, e-mail: reviews-help@spark.apache.org


Re: [PR] [DO-NOT-REVIEW][DRAFT] Spark 45637 multiple state test [spark]

Posted by "WweiL (via GitHub)" <gi...@apache.org>.
WweiL commented on code in PR #44076:
URL: https://github.com/apache/spark/pull/44076#discussion_r1411160900


##########
sql/core/src/main/scala/org/apache/spark/sql/execution/streaming/StreamingSymmetricHashJoinExec.scala:
##########
@@ -637,18 +653,22 @@ case class StreamingSymmetricHashJoinExec(
         thisRow: UnsafeRow,
         subIter: Iterator[InternalRow])
       extends CompletionIterator[InternalRow, Iterator[InternalRow]](subIter) {
-
+      // scalastyle:off
       private val iteratorNotEmpty: Boolean = super.hasNext
 
       override def completion(): Unit = {
         val isLeftSemiWithMatch =
           joinType == LeftSemi && joinSide == LeftSide && iteratorNotEmpty
         // Add to state store only if both removal predicates do not match,
         // and the row is not matched for left side of left semi join.
+        println(s"!stateKeyWatermarkPredicateFunc(key): ${!stateKeyWatermarkPredicateFunc(key)}" +
+          s" !stateValueWatermarkPredicateFunc(thisRow): ${!stateValueWatermarkPredicateFunc(thisRow)}")
         val shouldAddToState =
           !stateKeyWatermarkPredicateFunc(key) && !stateValueWatermarkPredicateFunc(thisRow) &&
           !isLeftSemiWithMatch
         if (shouldAddToState) {
+          println(s"wei==add to state: $thisRow")

Review Comment:
   So what happens here is in the no data batch, the wm of `stateKeyWatermarkPredicateFunc` is updated to the new global wm (8). However the emitted key from both parent window aggregations are [0, 5), hence `stateKeyWatermarkPredicateFunc(key)` returns true, meaning that the window is not added to the join state store.
   
   This is wrong, because the two [0, 5) windows should be joined here. At least one side of the window should be added to the state store, so the other side could load it and join. But because of this check, the row from both sides aren't added to the state and they can't be joined
   
   This looks like some updates to the multiple state operators that we need to consider



-- 
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: reviews-unsubscribe@spark.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: reviews-unsubscribe@spark.apache.org
For additional commands, e-mail: reviews-help@spark.apache.org


Re: [PR] [DO-NOT-REVIEW][DRAFT] Spark 45637 multiple state test [spark]

Posted by "WweiL (via GitHub)" <gi...@apache.org>.
WweiL commented on code in PR #44076:
URL: https://github.com/apache/spark/pull/44076#discussion_r1437952483


##########
sql/core/src/test/scala/org/apache/spark/sql/streaming/MultiStatefulOperatorsSuite.scala:
##########
@@ -814,68 +814,183 @@ class MultiStatefulOperatorsSuite
     }
   }
 
-  test("stream-stream time interval join - output watermark for various intervals") {
-    def testOutputWatermarkInJoin(
-        df: DataFrame,
-        input: MemoryStream[(String, Timestamp)],
-        expectedOutputWatermark: Long): Unit = {
-      testStream(df)(
-        // dummy row to trigger execution
-        AddData(input, ("1", Timestamp.valueOf("2023-01-01 01:00:10"))),
-        CheckAnswer(),
-        Execute { query =>
-          val lastExecution = query.lastExecution
-          val joinOperator = lastExecution.executedPlan.collect {
-            case j: StreamingSymmetricHashJoinExec => j
-          }.head
+  test("SPARK-45637-1 join on window, append mode") {

Review Comment:
   ```
   -=-=-=-=-=-=-=
   currentBatchId = 0, lastExecutionRequiresAnotherBatch = false, isNewDataAvailable = true, shouldConstructNextBatch (with currbatchID) = true
   stateKeyWatermarkPredicateFunc: (input[0, struct<start:timestamp,end:timestamp>, false].end <= 0)
   stateKeyWatermarkPredicateFunc: (input[0, struct<start:timestamp,end:timestamp>, false].end <= 0)
   wei==thisrow: [0,1000000018,0,0,4c4b40]
   this row filtered: [0,1000000018,0,0,4c4b40]
   getJoinedRows ------ key: [0,1000000018,0,0,4c4b40] numValues: 0
   !stateKeyWatermarkPredicateFunc(key): true !stateValueWatermarkPredicateFunc(thisRow): true
   wei==add to state: [0,1000000018,0,0,4c4b40]
   wei==thisrow: [0,1000000018,0,4c4b40,989680]
   this row filtered: [0,1000000018,0,4c4b40,989680]
   getJoinedRows ------ key: [0,1000000018,0,4c4b40,989680] numValues: 0
   !stateKeyWatermarkPredicateFunc(key): true !stateValueWatermarkPredicateFunc(thisRow): true
   wei==add to state: [0,1000000018,0,4c4b40,989680]
   wei==thisrow: [0,1000000018,0,0,4c4b40]
   this row filtered: [0,1000000018,0,0,4c4b40]
   getJoinedRows ------ key: [0,1000000018,0,0,4c4b40] numValues: 1
   joinedRow: {[0,1000000018,0,0,4c4b40] + [0,1000000018,0,0,4c4b40]}
   ---joinedRow emitted
   !stateKeyWatermarkPredicateFunc(key): true !stateValueWatermarkPredicateFunc(thisRow): true
   wei==add to state: [0,1000000018,0,0,4c4b40]
   wei==thisrow: [0,1000000018,0,0,4c4b40]
   this row filtered: [0,1000000018,0,0,4c4b40]
   getJoinedRows ------ key: [0,1000000018,0,0,4c4b40] numValues: 1
   joinedRow: {[0,1000000018,0,0,4c4b40] + [0,1000000018,0,0,4c4b40]}
   ---joinedRow emitted
   !stateKeyWatermarkPredicateFunc(key): true !stateValueWatermarkPredicateFunc(thisRow): true
   wei==add to state: [0,1000000018,0,0,4c4b40]
   wei==thisrow: [0,1000000018,0,0,4c4b40]
   this row filtered: [0,1000000018,0,0,4c4b40]
   getJoinedRows ------ key: [0,1000000018,0,0,4c4b40] numValues: 1
   joinedRow: {[0,1000000018,0,0,4c4b40] + [0,1000000018,0,0,4c4b40]}
   ---joinedRow emitted
   !stateKeyWatermarkPredicateFunc(key): true !stateValueWatermarkPredicateFunc(thisRow): true
   wei==add to state: [0,1000000018,0,0,4c4b40]
   wei==thisrow: [0,1000000018,0,0,4c4b40]
   this row filtered: [0,1000000018,0,0,4c4b40]
   getJoinedRows ------ key: [0,1000000018,0,0,4c4b40] numValues: 1
   joinedRow: {[0,1000000018,0,0,4c4b40] + [0,1000000018,0,0,4c4b40]}
   ---joinedRow emitted
   !stateKeyWatermarkPredicateFunc(key): true !stateValueWatermarkPredicateFunc(thisRow): true
   wei==add to state: [0,1000000018,0,0,4c4b40]
   wei==thisrow: [0,1000000018,0,0,4c4b40]
   this row filtered: [0,1000000018,0,0,4c4b40]
   getJoinedRows ------ key: [0,1000000018,0,0,4c4b40] numValues: 1
   joinedRow: {[0,1000000018,0,0,4c4b40] + [0,1000000018,0,0,4c4b40]}
   ---joinedRow emitted
   !stateKeyWatermarkPredicateFunc(key): true !stateValueWatermarkPredicateFunc(thisRow): true
   wei==add to state: [0,1000000018,0,0,4c4b40]
   wei==thisrow: [0,1000000018,0,4c4b40,989680]
   this row filtered: [0,1000000018,0,4c4b40,989680]
   getJoinedRows ------ key: [0,1000000018,0,4c4b40,989680] numValues: 1
   joinedRow: {[0,1000000018,0,4c4b40,989680] + [0,1000000018,0,4c4b40,989680]}
   ---joinedRow emitted
   !stateKeyWatermarkPredicateFunc(key): true !stateValueWatermarkPredicateFunc(thisRow): true
   wei==add to state: [0,1000000018,0,4c4b40,989680]
   wei==thisrow: [0,1000000018,0,4c4b40,989680]
   this row filtered: [0,1000000018,0,4c4b40,989680]
   getJoinedRows ------ key: [0,1000000018,0,4c4b40,989680] numValues: 1
   joinedRow: {[0,1000000018,0,4c4b40,989680] + [0,1000000018,0,4c4b40,989680]}
   ---joinedRow emitted
   !stateKeyWatermarkPredicateFunc(key): true !stateValueWatermarkPredicateFunc(thisRow): true
   wei==add to state: [0,1000000018,0,4c4b40,989680]
   wei==thisrow: [0,1000000018,0,4c4b40,989680]
   this row filtered: [0,1000000018,0,4c4b40,989680]
   getJoinedRows ------ key: [0,1000000018,0,4c4b40,989680] numValues: 1
   joinedRow: {[0,1000000018,0,4c4b40,989680] + [0,1000000018,0,4c4b40,989680]}
   ---joinedRow emitted
   !stateKeyWatermarkPredicateFunc(key): true !stateValueWatermarkPredicateFunc(thisRow): true
   wei==add to state: [0,1000000018,0,4c4b40,989680]
   wei==thisrow: [0,1000000018,0,4c4b40,989680]
   this row filtered: [0,1000000018,0,4c4b40,989680]
   getJoinedRows ------ key: [0,1000000018,0,4c4b40,989680] numValues: 1
   joinedRow: {[0,1000000018,0,4c4b40,989680] + [0,1000000018,0,4c4b40,989680]}
   ---joinedRow emitted
   !stateKeyWatermarkPredicateFunc(key): true !stateValueWatermarkPredicateFunc(thisRow): true
   wei==add to state: [0,1000000018,0,4c4b40,989680]
   allKeyToNumValues.hasNext: true
   ---------------removeByKeyCondition--------------- allKeyToNumValues.hasNext
   18:21:47.427 ERROR org.apache.spark.util.Utils: Aborting task
   java.lang.NullPointerException: Cannot invoke "org.apache.spark.sql.execution.streaming.state.SymmetricHashJoinStateManager$KeyAndNumValues.key()" because the return value of "org.apache.spark.sql.execution.streaming.state.SymmetricHashJoinStateManager$$anon$1.currentKeyToNumValue()" is null
   	at org.apache.spark.sql.execution.streaming.state.SymmetricHashJoinStateManager$$anon$1.currentKey(SymmetricHashJoinStateManager.scala:155)
   	at org.apache.spark.sql.execution.streaming.state.SymmetricHashJoinStateManager$$anon$1.getNext(SymmetricHashJoinStateManager.scala:178)
   	at org.apache.spark.sql.execution.streaming.state.SymmetricHashJoinStateManager$$anon$1.getNext(SymmetricHashJoinStateManager.scala:148)
   	at org.apache.spark.util.NextIterator.hasNext(NextIterator.scala:73)
   	at scala.collection.Iterator$ConcatIterator.hasNext(Iterator.scala:1149)
   	at org.apache.spark.sql.execution.streaming.StreamingSymmetricHashJoinExec.$anonfun$processPartitions$25(StreamingSymmetricHashJoinExec.scala:479)
   	at scala.runtime.java8.JFunction0$mcV$sp.apply(JFunction0$mcV$sp.scala:18)
   18:21:47.429 ERROR org.apache.spark.sql.execution.datasources.v2.DataWritingSparkTask: Aborting commit for partition 0 (task 2, attempt 0, stage 2.0)
   18:21:47.429 ERROR org.apache.spark.sql.execution.datasources.v2.DataWritingSparkTask: Aborted commit for partition 0 (task 2, attempt 0, stage 2.0)
   18:21:47.438 ERROR org.apache.spark.executor.Executor: Exception in task 0.0 in stage 2.0 (TID 2)
   java.lang.NullPointerException: Cannot invoke "org.apache.spark.sql.execution.streaming.state.SymmetricHashJoinStateManager$KeyAndNumValues.key()" because the return value of "org.apache.spark.sql.execution.streaming.state.SymmetricHashJoinStateManager$$anon$1.currentKeyToNumValue()" is null
   	at org.apache.spark.sql.execution.streaming.state.SymmetricHashJoinStateManager$$anon$1.currentKey(SymmetricHashJoinStateManager.scala:155)
   	at org.apache.spark.sql.execution.streaming.state.SymmetricHashJoinStateManager$$anon$1.getNext(SymmetricHashJoinStateManager.scala:178)
   	at org.apache.spark.sql.execution.streaming.state.SymmetricHashJoinStateManager$$anon$1.getNext(SymmetricHashJoinStateManager.scala:148)
   	at org.apache.spark.util.NextIterator.hasNext(NextIterator.scala:73)
   	at scala.collection.Iterator$ConcatIterator.hasNext(Iterator.scala:1149)
   	at org.apache.spark.sql.execution.streaming.StreamingSymmetricHashJoinExec.$anonfun$processPartitions$25(StreamingSymmetricHashJoinExec.scala:479)
   	at scala.runtime.java8.JFunction0$mcV$sp.apply(JFunction0$mcV$sp.scala:18)
   18:21:47.445 WARN org.apache.spark.scheduler.TaskSetManager: Lost task 0.0 in stage 2.0 (TID 2) (10.0.0.11 executor driver): java.lang.NullPointerException: Cannot invoke "org.apache.spark.sql.execution.streaming.state.SymmetricHashJoinStateManager$KeyAndNumValues.key()" because the return value of "org.apache.spark.sql.execution.streaming.state.SymmetricHashJoinStateManager$$anon$1.currentKeyToNumValue()" is null
   	at org.apache.spark.sql.execution.streaming.state.SymmetricHashJoinStateManager$$anon$1.currentKey(SymmetricHashJoinStateManager.scala:155)
   	at org.apache...
   18:21:47.446 ERROR org.apache.spark.scheduler.TaskSetManager: Task 0 in stage 2.0 failed 1 times; aborting job
   18:21:47.450 ERROR org.apache.spark.sql.execution.datasources.v2.WriteToDataSourceV2Exec: Data source write support MicroBatchWrite[epoch: 0, writer: org.apache.spark.sql.execution.streaming.sources.MemoryStreamingWrite@553911d0] is aborting.
   18:21:47.450 ERROR org.apache.spark.sql.execution.datasources.v2.WriteToDataSourceV2Exec: Data source write support MicroBatchWrite[epoch: 0, writer: org.apache.spark.sql.execution.streaming.sources.MemoryStreamingWrite@553911d0] aborted.
   18:21:47.496 ERROR org.apache.spark.sql.execution.streaming.MicroBatchExecution: Query [id = 716405ff-bb4c-4d94-8604-6d160c7b6ab9, runId = 39081f98-c9a5-4def-a219-d5a119cbda74] terminated with error
   org.apache.spark.SparkException: Job aborted due to stage failure: Task 0 in stage 2.0 failed 1 times, most recent failure: Lost task 0.0 in stage 2.0 (TID 2) (10.0.0.11 executor driver): java.lang.NullPointerException: Cannot invoke "org.apache.spark.sql.execution.streaming.state.SymmetricHashJoinStateManager$KeyAndNumValues.key()" because the return value of "org.apache.spark.sql.execution.streaming.state.SymmetricHashJoinStateManager$$anon$1.currentKeyToNumValue()" is null
   	at org.apache.spark.sql.execution.streaming.state.SymmetricHashJoinStateManager$$anon$1.currentKey(SymmetricHashJoinStateManager.scala:155)
   	at org.apache.spark.sql.execution.streaming.state.SymmetricHashJoinStateManager$$anon$1.getNext(SymmetricHashJoinStateManager.scala:178)
   	at org.apache.spark.sql.execution.streaming.state.SymmetricHashJoinStateManager$$anon$1.getNext(SymmetricHashJoinStateManager.scala:148)
   	at org.apache.spark.util.NextIterator.hasNext(NextIterator.scala:73)
   	at scala.collection.Iterator$ConcatIterator.hasNext(Iterator.scala:1149)
   	at org.apache.spark.sql.execution.streaming.StreamingSymmetricHashJoinExec.$anonfun$processPartitions$25(StreamingSymmetricHashJoinExec.scala:479)
   	at scala.runtime.java8.JFunction0$mcV$sp.apply(JFunction0$mcV$sp.scala:18)
   ```



-- 
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: reviews-unsubscribe@spark.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: reviews-unsubscribe@spark.apache.org
For additional commands, e-mail: reviews-help@spark.apache.org


Re: [PR] [DO-NOT-REVIEW][DRAFT] Spark 45637 multiple state test [spark]

Posted by "WweiL (via GitHub)" <gi...@apache.org>.
WweiL commented on code in PR #44076:
URL: https://github.com/apache/spark/pull/44076#discussion_r1437953509


##########
sql/core/src/main/scala/org/apache/spark/sql/execution/streaming/StreamingSymmetricHashJoinExec.scala:
##########
@@ -637,18 +653,22 @@ case class StreamingSymmetricHashJoinExec(
         thisRow: UnsafeRow,
         subIter: Iterator[InternalRow])
       extends CompletionIterator[InternalRow, Iterator[InternalRow]](subIter) {
-
+      // scalastyle:off
       private val iteratorNotEmpty: Boolean = super.hasNext
 
       override def completion(): Unit = {
         val isLeftSemiWithMatch =
           joinType == LeftSemi && joinSide == LeftSide && iteratorNotEmpty
         // Add to state store only if both removal predicates do not match,
         // and the row is not matched for left side of left semi join.
+        println(s"!stateKeyWatermarkPredicateFunc(key): ${!stateKeyWatermarkPredicateFunc(key)}" +
+          s" !stateValueWatermarkPredicateFunc(thisRow): ${!stateValueWatermarkPredicateFunc(thisRow)}")
         val shouldAddToState =
           !stateKeyWatermarkPredicateFunc(key) && !stateValueWatermarkPredicateFunc(thisRow) &&
           !isLeftSemiWithMatch
         if (shouldAddToState) {
+          println(s"wei==add to state: $thisRow")

Review Comment:
   https://github.com/apache/spark/commit/991726f31a8d182ed6d5b0e59185d97c0c5c532f



-- 
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: reviews-unsubscribe@spark.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: reviews-unsubscribe@spark.apache.org
For additional commands, e-mail: reviews-help@spark.apache.org


Re: [PR] [DO-NOT-REVIEW][DRAFT] Spark 45637 multiple state test [spark]

Posted by "WweiL (via GitHub)" <gi...@apache.org>.
WweiL commented on code in PR #44076:
URL: https://github.com/apache/spark/pull/44076#discussion_r1411160900


##########
sql/core/src/main/scala/org/apache/spark/sql/execution/streaming/StreamingSymmetricHashJoinExec.scala:
##########
@@ -637,18 +653,22 @@ case class StreamingSymmetricHashJoinExec(
         thisRow: UnsafeRow,
         subIter: Iterator[InternalRow])
       extends CompletionIterator[InternalRow, Iterator[InternalRow]](subIter) {
-
+      // scalastyle:off
       private val iteratorNotEmpty: Boolean = super.hasNext
 
       override def completion(): Unit = {
         val isLeftSemiWithMatch =
           joinType == LeftSemi && joinSide == LeftSide && iteratorNotEmpty
         // Add to state store only if both removal predicates do not match,
         // and the row is not matched for left side of left semi join.
+        println(s"!stateKeyWatermarkPredicateFunc(key): ${!stateKeyWatermarkPredicateFunc(key)}" +
+          s" !stateValueWatermarkPredicateFunc(thisRow): ${!stateValueWatermarkPredicateFunc(thisRow)}")
         val shouldAddToState =
           !stateKeyWatermarkPredicateFunc(key) && !stateValueWatermarkPredicateFunc(thisRow) &&
           !isLeftSemiWithMatch
         if (shouldAddToState) {
+          println(s"wei==add to state: $thisRow")

Review Comment:
   So what happens here is in the no data batch, the wm of `stateKeyWatermarkPredicateFunc` is updated to the new global wm (8). However the emitted key from both parent window aggregations are [0, 5), hence `stateKeyWatermarkPredicateFunc(key)` returns true, meaning that the window should not be added to the join state store.
   
   This is wrong, because the two [0, 5) windows should be joined here. 
   
   This looks like some updates to the multiple state operators that we need to consider



-- 
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: reviews-unsubscribe@spark.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: reviews-unsubscribe@spark.apache.org
For additional commands, e-mail: reviews-help@spark.apache.org


Re: [PR] [DO-NOT-REVIEW][DRAFT] Spark 45637 multiple state test [spark]

Posted by "WweiL (via GitHub)" <gi...@apache.org>.
WweiL commented on code in PR #44076:
URL: https://github.com/apache/spark/pull/44076#discussion_r1411160900


##########
sql/core/src/main/scala/org/apache/spark/sql/execution/streaming/StreamingSymmetricHashJoinExec.scala:
##########
@@ -637,18 +653,22 @@ case class StreamingSymmetricHashJoinExec(
         thisRow: UnsafeRow,
         subIter: Iterator[InternalRow])
       extends CompletionIterator[InternalRow, Iterator[InternalRow]](subIter) {
-
+      // scalastyle:off
       private val iteratorNotEmpty: Boolean = super.hasNext
 
       override def completion(): Unit = {
         val isLeftSemiWithMatch =
           joinType == LeftSemi && joinSide == LeftSide && iteratorNotEmpty
         // Add to state store only if both removal predicates do not match,
         // and the row is not matched for left side of left semi join.
+        println(s"!stateKeyWatermarkPredicateFunc(key): ${!stateKeyWatermarkPredicateFunc(key)}" +
+          s" !stateValueWatermarkPredicateFunc(thisRow): ${!stateValueWatermarkPredicateFunc(thisRow)}")
         val shouldAddToState =
           !stateKeyWatermarkPredicateFunc(key) && !stateValueWatermarkPredicateFunc(thisRow) &&
           !isLeftSemiWithMatch
         if (shouldAddToState) {
+          println(s"wei==add to state: $thisRow")

Review Comment:
   So what happens here is in the no data batch, the wm of `stateKeyWatermarkPredicateFunc` is updated to the new global wm (8). However the emitted key from both parent window aggregations are [0, 5), hence `stateKeyWatermarkPredicateFunc(key)` returns true, meaning that the window is not added to the join state store. As a result, when later `SymmetricHashJoinStateManager.getJoinedRows` wants to load the other side's stored row, it loads nothing.
   
   This is wrong, because the two [0, 5) windows should be joined here. At least one side of the window should be added to the state store, so the other side could load it and join. 
   
   This looks like some updates to the multiple state operators that we need to consider



-- 
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: reviews-unsubscribe@spark.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: reviews-unsubscribe@spark.apache.org
For additional commands, e-mail: reviews-help@spark.apache.org


Re: [PR] [DO-NOT-REVIEW][DRAFT] Spark 45637 multiple state test [spark]

Posted by "WweiL (via GitHub)" <gi...@apache.org>.
WweiL commented on code in PR #44076:
URL: https://github.com/apache/spark/pull/44076#discussion_r1411160900


##########
sql/core/src/main/scala/org/apache/spark/sql/execution/streaming/StreamingSymmetricHashJoinExec.scala:
##########
@@ -637,18 +653,22 @@ case class StreamingSymmetricHashJoinExec(
         thisRow: UnsafeRow,
         subIter: Iterator[InternalRow])
       extends CompletionIterator[InternalRow, Iterator[InternalRow]](subIter) {
-
+      // scalastyle:off
       private val iteratorNotEmpty: Boolean = super.hasNext
 
       override def completion(): Unit = {
         val isLeftSemiWithMatch =
           joinType == LeftSemi && joinSide == LeftSide && iteratorNotEmpty
         // Add to state store only if both removal predicates do not match,
         // and the row is not matched for left side of left semi join.
+        println(s"!stateKeyWatermarkPredicateFunc(key): ${!stateKeyWatermarkPredicateFunc(key)}" +
+          s" !stateValueWatermarkPredicateFunc(thisRow): ${!stateValueWatermarkPredicateFunc(thisRow)}")
         val shouldAddToState =
           !stateKeyWatermarkPredicateFunc(key) && !stateValueWatermarkPredicateFunc(thisRow) &&
           !isLeftSemiWithMatch
         if (shouldAddToState) {
+          println(s"wei==add to state: $thisRow")

Review Comment:
   So what happens here is in the no data batch, the wm of `stateKeyWatermarkPredicateFunc` is updated to the new global wm (8). However the emitted key from both parent window aggregations are [0, 5), hence `stateKeyWatermarkPredicateFunc(key)` returns true, meaning that the window is not added to the join state store. As a result, when later `SymmetricHashJoinStateManager.getJoinedRows` wants to load the other side's stored row, it loads nothing.
   
   This is wrong, because the two [0, 5) windows should be joined here. At least one side of the window should be added to the state store, so the other side could load it and join. But because of this check, the row from both sides aren't added to the state and they can't be joined
   
   This looks like some updates to the multiple state operators that we need to consider



-- 
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: reviews-unsubscribe@spark.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: reviews-unsubscribe@spark.apache.org
For additional commands, e-mail: reviews-help@spark.apache.org


Re: [PR] [DO-NOT-REVIEW][DRAFT] Spark 45637 multiple state test [spark]

Posted by "WweiL (via GitHub)" <gi...@apache.org>.
WweiL commented on code in PR #44076:
URL: https://github.com/apache/spark/pull/44076#discussion_r1411160900


##########
sql/core/src/main/scala/org/apache/spark/sql/execution/streaming/StreamingSymmetricHashJoinExec.scala:
##########
@@ -637,18 +653,22 @@ case class StreamingSymmetricHashJoinExec(
         thisRow: UnsafeRow,
         subIter: Iterator[InternalRow])
       extends CompletionIterator[InternalRow, Iterator[InternalRow]](subIter) {
-
+      // scalastyle:off
       private val iteratorNotEmpty: Boolean = super.hasNext
 
       override def completion(): Unit = {
         val isLeftSemiWithMatch =
           joinType == LeftSemi && joinSide == LeftSide && iteratorNotEmpty
         // Add to state store only if both removal predicates do not match,
         // and the row is not matched for left side of left semi join.
+        println(s"!stateKeyWatermarkPredicateFunc(key): ${!stateKeyWatermarkPredicateFunc(key)}" +
+          s" !stateValueWatermarkPredicateFunc(thisRow): ${!stateValueWatermarkPredicateFunc(thisRow)}")
         val shouldAddToState =
           !stateKeyWatermarkPredicateFunc(key) && !stateValueWatermarkPredicateFunc(thisRow) &&
           !isLeftSemiWithMatch
         if (shouldAddToState) {
+          println(s"wei==add to state: $thisRow")

Review Comment:
   So what happens here is in the no data batch, the wm of `stateKeyWatermarkPredicateFunc` is updated to the new global wm (8). However the emitted key from both parent window aggregations are [0, 5), hence `stateKeyWatermarkPredicateFunc(key)` returns true, meaning that the window should not be added to the join state store.
   
   This is wrong, because the two [0, 5) windows should be joined here. At least one side of the window should be added to the state store, so the other side could load it and join. But because of this check, the row from both sides aren't added to the state and they can't be joined
   
   This looks like some updates to the multiple state operators that we need to consider



-- 
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: reviews-unsubscribe@spark.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: reviews-unsubscribe@spark.apache.org
For additional commands, e-mail: reviews-help@spark.apache.org


Re: [PR] [DO-NOT-REVIEW][DRAFT] Spark 45637 multiple state test [spark]

Posted by "WweiL (via GitHub)" <gi...@apache.org>.
WweiL commented on code in PR #44076:
URL: https://github.com/apache/spark/pull/44076#discussion_r1409960967


##########
sql/core/src/test/scala/org/apache/spark/sql/streaming/MultiStatefulOperatorsSuite.scala:
##########
@@ -814,68 +814,183 @@ class MultiStatefulOperatorsSuite
     }
   }
 
-  test("stream-stream time interval join - output watermark for various intervals") {
-    def testOutputWatermarkInJoin(
-        df: DataFrame,
-        input: MemoryStream[(String, Timestamp)],
-        expectedOutputWatermark: Long): Unit = {
-      testStream(df)(
-        // dummy row to trigger execution
-        AddData(input, ("1", Timestamp.valueOf("2023-01-01 01:00:10"))),
-        CheckAnswer(),
-        Execute { query =>
-          val lastExecution = query.lastExecution
-          val joinOperator = lastExecution.executedPlan.collect {
-            case j: StreamingSymmetricHashJoinExec => j
-          }.head
+  test("SPARK-45637-1 join on window, append mode") {

Review Comment:
   This is for me to understand the behavior of no agg window join
   



-- 
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: reviews-unsubscribe@spark.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: reviews-unsubscribe@spark.apache.org
For additional commands, e-mail: reviews-help@spark.apache.org


Re: [PR] [DO-NOT-REVIEW][DRAFT] Spark 45637 multiple state test [spark]

Posted by "WweiL (via GitHub)" <gi...@apache.org>.
WweiL commented on PR #44076:
URL: https://github.com/apache/spark/pull/44076#issuecomment-1834480537

   https://github.com/apache/spark/commit/75d666b95a711787355ca3895057dabadd429023
   Seems like the prejoinFilter is just an optimization, i need to understand the cause of removing it


-- 
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: reviews-unsubscribe@spark.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: reviews-unsubscribe@spark.apache.org
For additional commands, e-mail: reviews-help@spark.apache.org


Re: [PR] [DO-NOT-REVIEW][DRAFT] Spark 45637 multiple state test [spark]

Posted by "github-actions[bot] (via GitHub)" <gi...@apache.org>.
github-actions[bot] closed pull request #44076: [DO-NOT-REVIEW][DRAFT] Spark 45637 multiple state test
URL: https://github.com/apache/spark/pull/44076


-- 
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: reviews-unsubscribe@spark.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: reviews-unsubscribe@spark.apache.org
For additional commands, e-mail: reviews-help@spark.apache.org