Dandandan opened a new pull request, #24794:
URL: https://github.com/apache/datafusion/pull/24794

   ## Which issue does this PR close?
   
   - Closes #.
   
   ## Rationale for this change
   
   A `LeftSemi` hash join emits nothing while probing. 
`adjust_indices_by_join_type`
   returns empty index arrays for it, and every matched build row comes out at 
the
   end from the visited bitmap, the same way `LeftAnti` and `LeftMark` work.
   
   `HashJoinExec::compute_properties` nevertheless reports
   `EmissionType::Incremental` for `LeftSemi`, grouped with `Inner` and
   `RightSemi` under the comment "If we only need to generate matched rows from
   the probe side". That is not what `LeftSemi` does: its rows come from the 
build
   side. `LeftAnti` and `LeftMark` are correctly classified `Both`.
   
   So the join is blocking, and a `LIMIT` above it buys nothing. On TPC-DS SF1:
   
   ```sql
   select ws_order_number from web_sales ws
   where exists (select 1 from web_returns wr
                 where wr.wr_order_number = ws.ws_order_number)
   limit 10
   ```
   
   | | |
   |---|---|
   | plans as `LeftSemi`, with `LIMIT 10` | 9.2 ms |
   | the same query with no `LIMIT` at all | 8.6 ms |
   | mirrored so it plans as `RightSemi`, with `LIMIT 10` | 2.8 ms |
   
   ## What changes are included in this PR?
   
   A semi join only needs to know whether a build row has matched yet, and the
   visited bitmap already carries that. This emits a build row when its bit 
flips
   from unset to set, which produces the same rows in the same order but while
   probing rather than after it. The final stage then has nothing left to do.
   
   The comment at that site already described the fix: "When visit the right
   batch, we can output the matched left row and don't need to wait the end of
   loop".
   
   The query above now takes 2.7 ms, matching the `RightSemi` form, and
   `EmissionType::Incremental` becomes true rather than aspirational.
   
   Only the hash join changes. `NestedLoopJoinExec` still emits its `LeftSemi`
   rows at the end, so `need_produce_result_in_final` is untouched.
   
   ## Are these changes tested?
   
   Yes, by the existing coverage: the full sqllogictest suite (504 files) and 
the
   1117 join unit tests pass. Semi joins are heavily covered by `joins.slt`,
   `subquery.slt` and the hash join's own tests, including across partition 
modes
   and batch sizes.
   
   One expectation changed, in `push_down_filter_parquet.slt`. It is an `EXPLAIN
   ANALYZE` whose join reports `input_batches=1, input_rows=2` where it used to
   report `2` and `4`; `output_rows` is 2 either way. The join no longer holds 
its
   output back, so the consumer finishes and the probe scan stops earlier.
   
   ## Are there any user-facing changes?
   
   `LeftSemi` hash joins are no longer blocking, so a `LIMIT` or any other
   early-terminating consumer above one can now stop it early. Results are
   unchanged.
   


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