tuantran0910 opened a new pull request, #69954:
URL: https://github.com/apache/doris/pull/69954

   ### What problem does this PR solve?
   
   Issue Number: close #69902
   
   Related PR: #55942
   
   Problem Summary:
   
   A shuffled hash join whose build side matches very few rows can lose its
   global runtime filter, so every probe-side scan reads the whole table. The
   result stays correct, but latency regresses (in the report, from about 0.2s
   to 10-30s, reading 74M rows instead of 1). It is intermittent; under
   concurrent load about 1-6% of the queries were affected.
   
   Reproduce: run a `RIGHT OUTER JOIN(PARTITIONED)` (or an inner/semi/anti join
   that short-circuits on an empty build side) with two join instances and a
   build side of one row. The probe-side scan profile then shows
   `state: [DISABLED] ... reason: get disabled from remote` with
   `reached_timeout: false`. Raising `runtime_filter_wait_time_ms` does not
   help, and `enable_sync_runtime_filter_size=false` only narrows the window.
   
   Root cause: the hash join build sink released its probe at eos, but built
   and published its runtime filters only later in close(), after waiting for
   the global filter size sync. On the instance with an empty build side (or a
   null key for a null-aware anti join), `short_circuit_for_probe` makes the
   probe return eos at once without reading its input. Its pipeline then
   closes, `Pipeline::make_all_runnable` wakes up the build task early, and
   `HashJoinBuildSinkLocalState::terminate` calls `skip_process()`, which
   publishes the filters as DISABLED. `RuntimeFilterWrapper::merge` treats a
   DISABLED input as absorbing, so the merged global filter is disabled for the
   probe-side scans of all instances.
   
   Fix: when the sink builds the hash table, has runtime filters and its probe
   short-circuits, release the probe in close(), after the runtime filters are
   published (also when close() fails). An empty build then publishes a READY,
   empty filter and the merged filter keeps the keys of the other instances.
   Do the same for the partitioned (spill) hash join sink when it is not
   spilled. A sink terminated before eos still falls back to skip_process(), so
   the guarantee of #55942 is kept. Cancellation and early wake-up still
   unblock the probe.
   
   Before: the probe-side scans intermittently got a disabled filter and read
   the whole table. After: they get the READY filter of the build side.
   
   ### Release note
   
   Fix a shuffled hash join intermittently disabling its global runtime filter
   when one join instance has an empty build side, which made the probe side
   scan the whole table.
   
   ### Check List (For Author)
   
   - Test: Regression test / Unit Test
       - BE UT `HashJoinBuildSinkTest.ReleaseShortCircuitProbeOnClose`
       - Regression test `query_p0/join/test_short_circuit_probe_runtime_filter`
         with a debug point that widens the race window
   - Behavior changed: Yes. A short-circuited probe now finishes after its
     build sink publishes the runtime filters, instead of at the build eos.
   - Does this need documentation: No
   
   Draft: not built locally yet; opened to run CI on the change and the new 
tests.
   
   🤖 Generated with [Claude Code](https://claude.com/claude-code)
   


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