This is an automated email from the ASF dual-hosted git repository.

github-actions[bot] pushed a commit to branch asf-site
in repository https://gitbox.apache.org/repos/asf/datafusion-ballista.git


The following commit(s) were added to refs/heads/asf-site by this push:
     new 2c07fae8a Publish built docs triggered by 
ac41a22245b563ec7bfba53e2d4b0783aa5c5318
2c07fae8a is described below

commit 2c07fae8ad7aa7f29bdc11c29c975d7d451fb614
Author: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
AuthorDate: Sat Jul 11 13:48:26 2026 +0000

    Publish built docs triggered by ac41a22245b563ec7bfba53e2d4b0783aa5c5318
---
 _sources/contributors-guide/architecture.md.txt | 62 +++++++++++++++++++++++++
 _sources/user-guide/tuning-guide.md.txt         | 12 ++---
 contributors-guide/architecture.html            | 62 +++++++++++++++++++++++++
 searchindex.js                                  |  2 +-
 user-guide/tuning-guide.html                    | 12 ++---
 5 files changed, 137 insertions(+), 13 deletions(-)

diff --git a/_sources/contributors-guide/architecture.md.txt 
b/_sources/contributors-guide/architecture.md.txt
index b25321d04..8a7ff1063 100644
--- a/_sources/contributors-guide/architecture.md.txt
+++ b/_sources/contributors-guide/architecture.md.txt
@@ -199,3 +199,65 @@ and [ShuffleReaderExec] operators.
 
 [shufflewriterexec]: 
https://github.com/apache/datafusion-ballista/blob/main/ballista/core/src/execution_plans/shuffle_writer.rs
 [shufflereaderexec]: 
https://github.com/apache/datafusion-ballista/blob/main/ballista/core/src/execution_plans/shuffle_reader.rs
+
+## Adaptive Query Execution (AQE)
+
+The scheduling described above is _static_: the full set of query stages is 
computed once, at job
+submission time, from the plan-time cost estimates. Adaptive Query Execution 
(AQE) is an experimental
+alternative in which the stage DAG is built _incrementally_, re-optimizing the 
remaining plan using the
+exact row counts and byte sizes observed as each shuffle stage completes. It 
is disabled by default and
+enabled with the `ballista.planner.adaptive.enabled` configuration setting.
+
+### Static vs adaptive execution graphs
+
+Job scheduling revolves around an `ExecutionGraph`, which translates a 
physical plan into a set of stages.
+There are two implementations, selected by configuration when a job is 
submitted:
+
+- **`StaticExecutionGraph`** — the default. All stages are planned up front by 
the `DistributedPlanner`,
+  which returns a static list of stages.
+- **`AdaptiveExecutionGraph`** — the adaptive counterpart. It is driven by the 
`AdaptivePlanner`, which runs
+  a set of pluggable physical optimizer rules after each stage completes and 
returns only the stages that are
+  currently runnable. Because decisions are deferred, stages come back already 
resolved, so the
+  `UnResolved` stage state used by the static path is not needed here.
+
+Keeping the two graphs side by side lets the adaptive implementation mature 
without destabilizing the static
+path.
+
+### How re-optimization works
+
+As each shuffle stage finishes, its exact output statistics are attached to 
the remaining plan and the
+optimizer rules are re-run. This is the key difference from DataFusion's 
normal single-shot physical
+optimization, where each rule runs once per plan. Running the full rule set 
repeatedly means the rules must be
+**idempotent** — otherwise they would keep inserting redundant exec nodes on 
each pass.
+
+Two adaptive optimizations are implemented today:
+
+- **Join reordering** — runtime row counts are used so the smaller side drives 
the join.
+- **Empty stage elimination** — when a completed stage produces zero rows, its 
downstream exchange is
+  replaced with an empty execution node and emptiness is propagated up the 
plan so dependent stages are
+  skipped entirely.
+
+### Code layout
+
+The adaptive scheduler code lives under [`ballista/scheduler/src/state/aqe`], 
with the
+`AdaptiveExecutionGraph` in `mod.rs`, the planner in `planner.rs`, and the 
optimizer rules in
+`optimizer_rule.rs`.
+
+### Current limitations
+
+The adaptive path currently covers the happy path only. Known gaps, each with 
a tracking issue:
+
+- Executor failure handling on the AQE path ([#1986])
+- Dynamic coalescing of shuffle partitions ([#1987])
+- Switching from hash join to sort-merge join based on runtime statistics 
([#1988])
+- Switching from streaming aggregation to hash aggregation based on runtime 
statistics ([#1989])
+
+Design and progress are tracked in the AQE epic ([#1359]). See also the
+[AQE section of the tuning guide](../user-guide/tuning-guide.md) for the 
user-facing description.
+
+[`ballista/scheduler/src/state/aqe`]: 
https://github.com/apache/datafusion-ballista/tree/main/ballista/scheduler/src/state/aqe
+[#1359]: https://github.com/apache/datafusion-ballista/issues/1359
+[#1986]: https://github.com/apache/datafusion-ballista/issues/1986
+[#1987]: https://github.com/apache/datafusion-ballista/issues/1987
+[#1988]: https://github.com/apache/datafusion-ballista/issues/1988
+[#1989]: https://github.com/apache/datafusion-ballista/issues/1989
diff --git a/_sources/user-guide/tuning-guide.md.txt 
b/_sources/user-guide/tuning-guide.md.txt
index 7b6f38130..b7906b166 100644
--- a/_sources/user-guide/tuning-guide.md.txt
+++ b/_sources/user-guide/tuning-guide.md.txt
@@ -218,14 +218,14 @@ implemented:
 The implementation covers the happy path only. The following are known to be
 missing or incomplete:
 
-- Executor failure handling on the AQE path
-- Dynamic coalescing of shuffle partitions
-- Switching from hash join to sort-merge join based on runtime statistics
-- Switching from streaming aggregation to hash aggregation based on runtime 
statistics
+- Executor failure handling on the AQE path 
([#1986](https://github.com/apache/datafusion-ballista/issues/1986))
+- Dynamic coalescing of shuffle partitions 
([#1987](https://github.com/apache/datafusion-ballista/issues/1987))
+- Switching from hash join to sort-merge join based on runtime statistics 
([#1988](https://github.com/apache/datafusion-ballista/issues/1988))
+- Switching from streaming aggregation to hash aggregation based on runtime 
statistics ([#1989](https://github.com/apache/datafusion-ballista/issues/1989))
 
 Until these gaps are closed, AQE should be used for testing and experimentation
-rather than production workloads. See [issue 
#387](https://github.com/apache/datafusion-ballista/issues/387)
-for the tracking issue and ongoing work.
+rather than production workloads. See [issue 
#1359](https://github.com/apache/datafusion-ballista/issues/1359)
+for the tracking epic and ongoing work.
 
 ## Push-based vs Pull-based Task Scheduling
 
diff --git a/contributors-guide/architecture.html 
b/contributors-guide/architecture.html
index f5148806d..9027a56dd 100644
--- a/contributors-guide/architecture.html
+++ b/contributors-guide/architecture.html
@@ -549,6 +549,61 @@ stage. This mechanism is known as an Exchange or a 
Shuffle. The logic for this c
 and <a class="reference external" 
href="https://github.com/apache/datafusion-ballista/blob/main/ballista/core/src/execution_plans/shuffle_reader.rs";>ShuffleReaderExec</a>
 operators.</p>
 </section>
 </section>
+<section id="adaptive-query-execution-aqe">
+<h2>Adaptive Query Execution (AQE)<a class="headerlink" 
href="#adaptive-query-execution-aqe" title="Link to this heading">#</a></h2>
+<p>The scheduling described above is <em>static</em>: the full set of query 
stages is computed once, at job
+submission time, from the plan-time cost estimates. Adaptive Query Execution 
(AQE) is an experimental
+alternative in which the stage DAG is built <em>incrementally</em>, 
re-optimizing the remaining plan using the
+exact row counts and byte sizes observed as each shuffle stage completes. It 
is disabled by default and
+enabled with the <code class="docutils literal notranslate"><span 
class="pre">ballista.planner.adaptive.enabled</span></code> configuration 
setting.</p>
+<section id="static-vs-adaptive-execution-graphs">
+<h3>Static vs adaptive execution graphs<a class="headerlink" 
href="#static-vs-adaptive-execution-graphs" title="Link to this 
heading">#</a></h3>
+<p>Job scheduling revolves around an <code class="docutils literal 
notranslate"><span class="pre">ExecutionGraph</span></code>, which translates a 
physical plan into a set of stages.
+There are two implementations, selected by configuration when a job is 
submitted:</p>
+<ul class="simple">
+<li><p><strong><code class="docutils literal notranslate"><span 
class="pre">StaticExecutionGraph</span></code></strong> — the default. All 
stages are planned up front by the <code class="docutils literal 
notranslate"><span class="pre">DistributedPlanner</span></code>,
+which returns a static list of stages.</p></li>
+<li><p><strong><code class="docutils literal notranslate"><span 
class="pre">AdaptiveExecutionGraph</span></code></strong> — the adaptive 
counterpart. It is driven by the <code class="docutils literal 
notranslate"><span class="pre">AdaptivePlanner</span></code>, which runs
+a set of pluggable physical optimizer rules after each stage completes and 
returns only the stages that are
+currently runnable. Because decisions are deferred, stages come back already 
resolved, so the
+<code class="docutils literal notranslate"><span 
class="pre">UnResolved</span></code> stage state used by the static path is not 
needed here.</p></li>
+</ul>
+<p>Keeping the two graphs side by side lets the adaptive implementation mature 
without destabilizing the static
+path.</p>
+</section>
+<section id="how-re-optimization-works">
+<h3>How re-optimization works<a class="headerlink" 
href="#how-re-optimization-works" title="Link to this heading">#</a></h3>
+<p>As each shuffle stage finishes, its exact output statistics are attached to 
the remaining plan and the
+optimizer rules are re-run. This is the key difference from DataFusion’s 
normal single-shot physical
+optimization, where each rule runs once per plan. Running the full rule set 
repeatedly means the rules must be
+<strong>idempotent</strong> — otherwise they would keep inserting redundant 
exec nodes on each pass.</p>
+<p>Two adaptive optimizations are implemented today:</p>
+<ul class="simple">
+<li><p><strong>Join reordering</strong> — runtime row counts are used so the 
smaller side drives the join.</p></li>
+<li><p><strong>Empty stage elimination</strong> — when a completed stage 
produces zero rows, its downstream exchange is
+replaced with an empty execution node and emptiness is propagated up the plan 
so dependent stages are
+skipped entirely.</p></li>
+</ul>
+</section>
+<section id="code-layout">
+<h3>Code layout<a class="headerlink" href="#code-layout" title="Link to this 
heading">#</a></h3>
+<p>The adaptive scheduler code lives under <a class="reference external" 
href="https://github.com/apache/datafusion-ballista/tree/main/ballista/scheduler/src/state/aqe";><code
 class="docutils literal notranslate"><span 
class="pre">ballista/scheduler/src/state/aqe</span></code></a>, with the
+<code class="docutils literal notranslate"><span 
class="pre">AdaptiveExecutionGraph</span></code> in <code class="docutils 
literal notranslate"><span class="pre">mod.rs</span></code>, the planner in 
<code class="docutils literal notranslate"><span 
class="pre">planner.rs</span></code>, and the optimizer rules in
+<code class="docutils literal notranslate"><span 
class="pre">optimizer_rule.rs</span></code>.</p>
+</section>
+<section id="current-limitations">
+<h3>Current limitations<a class="headerlink" href="#current-limitations" 
title="Link to this heading">#</a></h3>
+<p>The adaptive path currently covers the happy path only. Known gaps, each 
with a tracking issue:</p>
+<ul class="simple">
+<li><p>Executor failure handling on the AQE path (<a class="reference 
external" 
href="https://github.com/apache/datafusion-ballista/issues/1986";>#1986</a>)</p></li>
+<li><p>Dynamic coalescing of shuffle partitions (<a class="reference external" 
href="https://github.com/apache/datafusion-ballista/issues/1987";>#1987</a>)</p></li>
+<li><p>Switching from hash join to sort-merge join based on runtime statistics 
(<a class="reference external" 
href="https://github.com/apache/datafusion-ballista/issues/1988";>#1988</a>)</p></li>
+<li><p>Switching from streaming aggregation to hash aggregation based on 
runtime statistics (<a class="reference external" 
href="https://github.com/apache/datafusion-ballista/issues/1989";>#1989</a>)</p></li>
+</ul>
+<p>Design and progress are tracked in the AQE epic (<a class="reference 
external" 
href="https://github.com/apache/datafusion-ballista/issues/1359";>#1359</a>). 
See also the
+<a class="reference internal" href="../user-guide/tuning-guide.html"><span 
class="std std-doc">AQE section of the tuning guide</span></a> for the 
user-facing description.</p>
+</section>
+</section>
 </section>
 
 
@@ -617,6 +672,13 @@ and <a class="reference external" 
href="https://github.com/apache/datafusion-bal
 <li class="toc-h3 nav-item toc-entry"><a class="reference internal nav-link" 
href="#shuffle">Shuffle</a></li>
 </ul>
 </li>
+<li class="toc-h2 nav-item toc-entry"><a class="reference internal nav-link" 
href="#adaptive-query-execution-aqe">Adaptive Query Execution (AQE)</a><ul 
class="nav section-nav flex-column">
+<li class="toc-h3 nav-item toc-entry"><a class="reference internal nav-link" 
href="#static-vs-adaptive-execution-graphs">Static vs adaptive execution 
graphs</a></li>
+<li class="toc-h3 nav-item toc-entry"><a class="reference internal nav-link" 
href="#how-re-optimization-works">How re-optimization works</a></li>
+<li class="toc-h3 nav-item toc-entry"><a class="reference internal nav-link" 
href="#code-layout">Code layout</a></li>
+<li class="toc-h3 nav-item toc-entry"><a class="reference internal nav-link" 
href="#current-limitations">Current limitations</a></li>
+</ul>
+</li>
 </ul>
   </nav></div>
 
diff --git a/searchindex.js b/searchindex.js
index 36beefa4a..92b81df85 100644
--- a/searchindex.js
+++ b/searchindex.js
@@ -1 +1 @@
-Search.setIndex({"alltitles":{"AQE join behavior 
(opt-in)":[[25,"aqe-join-behavior-opt-in"]],"Adaptive Query Execution 
(Experimental)":[[47,"adaptive-query-execution-experimental"]],"Aggregate 
Functions":[[46,"aggregate-functions"]],"Apache DataFusion 
Ballista":[[24,null]],"Apache DataFusion Ballista 0.10.0 
Changelog":[[0,null]],"Apache DataFusion Ballista 0.11.0 
Changelog":[[1,null]],"Apache DataFusion Ballista 0.12.0 
Changelog":[[2,null]],"Apache DataFusion Ballista 0.5.0 Changelog":[[ [...]
\ No newline at end of file
+Search.setIndex({"alltitles":{"AQE join behavior 
(opt-in)":[[25,"aqe-join-behavior-opt-in"]],"Adaptive Query Execution 
(AQE)":[[21,"adaptive-query-execution-aqe"]],"Adaptive Query Execution 
(Experimental)":[[47,"adaptive-query-execution-experimental"]],"Aggregate 
Functions":[[46,"aggregate-functions"]],"Apache DataFusion 
Ballista":[[24,null]],"Apache DataFusion Ballista 0.10.0 
Changelog":[[0,null]],"Apache DataFusion Ballista 0.11.0 
Changelog":[[1,null]],"Apache DataFusion Ballista 0.12. [...]
\ No newline at end of file
diff --git a/user-guide/tuning-guide.html b/user-guide/tuning-guide.html
index f5fe67091..98de61e7c 100644
--- a/user-guide/tuning-guide.html
+++ b/user-guide/tuning-guide.html
@@ -605,14 +605,14 @@ is propagated up the plan so downstream stages are 
skipped entirely.</p></li>
 <p>The implementation covers the happy path only. The following are known to be
 missing or incomplete:</p>
 <ul class="simple">
-<li><p>Executor failure handling on the AQE path</p></li>
-<li><p>Dynamic coalescing of shuffle partitions</p></li>
-<li><p>Switching from hash join to sort-merge join based on runtime 
statistics</p></li>
-<li><p>Switching from streaming aggregation to hash aggregation based on 
runtime statistics</p></li>
+<li><p>Executor failure handling on the AQE path (<a class="reference 
external" 
href="https://github.com/apache/datafusion-ballista/issues/1986";>#1986</a>)</p></li>
+<li><p>Dynamic coalescing of shuffle partitions (<a class="reference external" 
href="https://github.com/apache/datafusion-ballista/issues/1987";>#1987</a>)</p></li>
+<li><p>Switching from hash join to sort-merge join based on runtime statistics 
(<a class="reference external" 
href="https://github.com/apache/datafusion-ballista/issues/1988";>#1988</a>)</p></li>
+<li><p>Switching from streaming aggregation to hash aggregation based on 
runtime statistics (<a class="reference external" 
href="https://github.com/apache/datafusion-ballista/issues/1989";>#1989</a>)</p></li>
 </ul>
 <p>Until these gaps are closed, AQE should be used for testing and 
experimentation
-rather than production workloads. See <a class="reference external" 
href="https://github.com/apache/datafusion-ballista/issues/387";>issue #387</a>
-for the tracking issue and ongoing work.</p>
+rather than production workloads. See <a class="reference external" 
href="https://github.com/apache/datafusion-ballista/issues/1359";>issue #1359</a>
+for the tracking epic and ongoing work.</p>
 </section>
 </section>
 <section id="push-based-vs-pull-based-task-scheduling">


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to