You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
docs(enterprise): clarify which execution mode distributes query work
Synchronous /v1/sql and FlightSQL queries fan out scans to executors but
run the rest of the plan on the scheduler. Only asynchronous /v1/queries
submissions are split into Ballista query stages and executed across
executors. Document the distinction, note the spice query CLI, and record
the 503 returned when state_location is unconfigured.
Copy file name to clipboardExpand all lines: enterprise/features/distributed-query.md
+18-6Lines changed: 18 additions & 6 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -181,7 +181,7 @@ The scheduler runs a `PartitionAssignmentTask` on `partition_assignment_interval
181
181
182
182
### Partition-aware query planning
183
183
184
-
The DataFusion analyzer rule `PartitionedTableScanRewrite` (scheduler-only) rewrites every `TableScan` on an accelerated table into a `UNION ALL` over per-executor FlightSQL scans, pushing down the executor's partition filter and any user predicates:
184
+
The DataFusion analyzer rule `PartitionedTableScanRewrite` runs on scheduler-role nodes and rewrites every `TableScan` on an accelerated table into a `UNION ALL` over per-executor FlightSQL scans, pushing down the executor's partition filter and any user predicates:
185
185
186
186
```text
187
187
Before:
@@ -202,6 +202,8 @@ Executor selection uses a greedy minimum set-cover algorithm: pick the executor
202
202
203
203
On executors, the `AcceleratedPartitionProvider` resolves partitions to local `TableProvider`s. Row-level partition predicates are not re-evaluated on executors — each executor only holds its own partitions, so filtering happens by ownership.
204
204
205
+
This rewrite is how [synchronous](#execution-modes) queries reach executor-resident data. Asynchronous queries do not use it — Ballista distributes their scans natively while planning query stages.
206
+
205
207
### Broadcast joins for small dimension tables
206
208
207
209
A join between a partitioned fact table and a small dimension table can be federated only at the scans, in which case every fact row travels up to the scheduler, which repartitions and joins centrally. On a large fact table, that transfer dominates query time.
@@ -300,12 +302,22 @@ Setting `snapshots: bootstrap_only` is recommended on executors when the source
| **Synchronous** | `/v1/sql`, FlightSQL | Client waits for the query to complete and receives results directly. Available in any deployment. |
306
-
| **Asynchronous** | `/v1/queries` | Client submits a query and polls a `query_id` for status. Full results are retrieved with pagination via `/v1/queries/{query_id}/results`, or chunk-by-chunk via `/v1/queries/{query_id}/results/chunks/{chunk_index}`. **Cluster (scheduler) mode only.** |
305
+
The two modes distribute work differently, and the choice determines whether a query becomes a multi-stage cluster job.
306
+
307
+
| Mode | Endpoint | How work is distributed | Notes |
| **Synchronous** | `/v1/sql`, FlightSQL | Scan fan-out only. The scheduler plans and runs the query itself, reading each partition from its owning executor over FlightSQL (see [Partition-aware query planning](#partition-aware-query-planning)). No cluster job, no query stages, no shuffles. | Client waits for the query to complete and receives results directly. Available in any deployment. |
310
+
| **Asynchronous** | `/v1/queries` | Full stage-based execution. The plan is split into Ballista query stages and dispatched as tasks to executors, which shuffle intermediate results between stages. | Client submits a query and polls a `query_id` for status. Full results are retrieved with pagination via `/v1/queries/{query_id}/results`, or chunk-by-chunk via `/v1/queries/{query_id}/results/chunks/{chunk_index}`. **Cluster (scheduler) mode only.** |
311
+
312
+
Only asynchronous queries create cluster jobs. A synchronous query against a partitioned accelerated table still reads from executors in parallel, but the joins, aggregations, and sorts above those scans run on the scheduler. Submit workloads whose cost sits above the scan — large joins, wide aggregations, distributed sorts — asynchronously so the cluster executes them across executors.
313
+
314
+
Submit an async query over HTTP with `POST /v1/queries`, or from the CLI with `spice query`, which submits the query and polls until it completes.
315
+
316
+
Async queries require `runtime.scheduler.state_location` to be configured. Without it the API returns `503`:
317
+
318
+
> Async queries API requires distributed mode with `runtime.scheduler.state_location` configured. Start with: `spiced --role scheduler`
307
319
308
-
Async queries require `runtime.scheduler.state_location` to be configured. Because job state is shared through that object store, an in-flight async query survives the loss of the scheduler that planned it — a surviving scheduler assumes ownership and continues driving it, and the client keeps polling the same `query_id`.
320
+
Because job state is shared through that object store, an in-flight async query survives the loss of the scheduler that planned it — a surviving scheduler assumes ownership and continues driving it, and the client keeps polling the same `query_id`.
0 commit comments