Using Adaptive Query Execution#
Adaptive Query Execution (AQE) lets Distributed DataFusion choose the number of tasks for each stage while the query is running. Instead of assigning every stage a task count statically at planning time, the coordinator samples each producer at its stage boundary and uses the observed data to size the stage above it.
AQE currently adapts distributed task counts. It does not rerun DataFusion’s physical optimizer or replace joins, aggregates, or other operators during execution. See How Adaptive Query Execution Works for the execution flow and sampling model.
Enable AQE#
Enable AQE on the coordinating session with
with_distributed_dynamic_task_count(true):
let state = SessionStateBuilder::new()
.with_default_features()
.with_distributed_worker_resolver(worker_resolver)
.with_distributed_planner()
+ .with_distributed_dynamic_task_count(true)?
.build();
Configuration#
The following settings affect AQE decisions:
Setting |
Default |
Effect |
|---|---|---|
|
|
Enables runtime task-count selection. |
|
16 MiB |
Sets the compute-cost budget per output partition. Lower values generally produce more tasks; higher values produce fewer. Configure it with |
Custom data sources#
AQE depends on both planning-time statistics and execution-time metrics. A custom leaf should provide all of the following:
A registered
TaskEstimatorthat implementsscale_up_leaf_nodefor the task count selected by AQE. Without an estimator, the planner treats an unknown leaf as limited to one task.A useful implementation of
ExecutionPlan::partition_statisticsin the custom data source. The more accurate the statistics are, the better the decisions AQE can make.Standard DataFusion execution metrics for the custom data source, including an
output_rowsmetric. AQE uses the output-row count of leaves on the stage’s driver path to measure sampling progress. If that metric is absent or not updated as batches flow, the coordinator cannot reliably extrapolate the final stage output.
Most of these requirements benefit the custom data source even when Distributed DataFusion is not involved, so taking the time to provide good implementations is always worthwhile.
Considerations#
There are a few things to take into account when using AQE:
Visualizing physical plans#
Plan visualization works out of the box with queries using AQE, but visualizing an unexecuted plan is not very useful. Task-count decisions have not yet been made, and network boundaries have not yet been injected, so you will effectively be visualizing the single-node plan before distribution.
This is not a bug; it is how AQE works: the final physical plan is decided dynamically at runtime.
When using AQE, prefer reading the final plan after the query has executed and all metrics have been collected from remote workers. See Collecting metrics from workers.
Distributed UNION operations#
AQE relies on runtime sampling to estimate the size of the different stages
involved in a query. When a UNION has multiple children and they all pull data
from remote stages, the stage cannot eagerly yield data from faster children.
It must wait for every child to be sampled before it can start.
This typically happens in systems that abuse UNION operations to model range
partitioning. There are many reasons to move away from this pattern, including
schema mismatches between children that silently introduce data loss, discarded
partitioning information, too many Tokio tasks caused by large child counts,
huge plans that are expensive to serialize, and unreadable EXPLAIN output. If
your system relies on this pattern, note that one consequence is an increased
time to first batch, even if the total query duration is unaffected.