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
compute: make the peek stash a state transition of one scan
Deletes the second walk a stashed peek used to cost. A peek whose accumulated
rows crossed the stash threshold abandoned its walk, and a separate path re-read
the trace bundle from the beginning to stream rows into persist. The offloaded
driver now writes each full batch as the walk produces it, so a peek walks its
arrangement exactly once whatever its answer turns out to be, and never returns
to the worker to reach the stash.
The upload becomes a handle the driver feeds. `StashUpload` keeps everything
about the persist interaction, the shard derived from the peek uuid, the schemas,
the batch builder and the `max_rows` early exit, and takes rows through `push`
instead of through a channel the worker pumps. `Complete` carries whatever the
scan still holds, and the driver assembles the answer around it: a driver that
never opened an upload answers with a row collection, and one that did finishes
and answers with the stashed handle, whose `inline_rows` carry the rows that
never reached the stash. The hand-back the layer below needed goes away, because
the task now has somewhere to write.
`PendingPeek` ends with fewer index-peek states than it had before this work
started. `PendingPeek::Stash`, `StashingPeek` and its worker-driven pump,
`start_stash_upload`, `PeekStatus::UsePeekStash` and `PEEK_STASH_NUM_BATCHES` are
all gone. `PEEK_STASH_BATCH_SIZE` goes too, against the plan: it counted rows,
the upload cuts a batch on the byte threshold the scan already tracks, and
nothing read it. A live tunable that does nothing is worse than an absent one,
because an operator who reaches for it gets silence rather than an error.
Two consequences worth stating plainly rather than discovering later.
The kill switch no longer means no peek ever leaves the worker. With
`UsePeekStash` gone, a large streamable peek would otherwise have no route to the
stash at all, which is a functional regression rather than a placement change.
The switch therefore gates the budget-based offload only: a scan that suspends
because its prefix is batch-ready is handed to a task whichever way the switch is
set, because that offload is for stashing rather than for latency. With the
switch off, ordinary peeks behave exactly as they do today.
The row iteration limit now follows a peek into the peek stash. #38158 stopped at
the stash because a stashed peek restarted its scan and the restart charged the
same rows twice. Deleting the restart is what this change does, so the count
simply continues because the scan does.
Cancellation deletes what it wrote. A cancelled peek used to leave the parts
already written in blob storage, since `impl Drop for Batch` only logs the
dangling keys and the reader-side delete runs after a successful read that a
cancelled peek never reaches. Cancellation aborts the offloaded task rather than
signalling it, so an await placed after the cancellation check would never run,
and the obligation lives on the upload itself: dropping one spawns a
`Batch::delete()` onto a runtime handle captured when it opened. A guard covers
the window inside `finish`, where persist has taken the builder and no upload
holds the parts any more.
Reclaiming those blobs must not cost more than it saves. A builder whose part
write was in flight when its walk was aborted holds a write persist has already
marked as waited on, and finishing it panics rather than returning; this replica
aborts the process on any uncaught panic, so reclaiming one query's blob storage
could take the replica with it. The panic is caught and the shard logged. Failing
to reclaim is an outcome this path already tolerates for a replica that dies
mid-upload, which makes a leak the right answer there and an abort the wrong one.
`mz_index_peek_stashed_total` counts the walks the stash answered. It is
incremented beside the offloaded substrate counter, so it is a strict subset by
construction, and every inline-driver test asserts it stays at zero.
`mz_stashed_peek_seconds` goes: its only observer was the deleted walk, and a
registered histogram that never observes reports a flat zero, which reads worse
in a graph than an absent series. The duration is deliberately not reconstructed,
because one loop now walks and writes, so the write is not separable from the
walk.
Copy file name to clipboardExpand all lines: doc/user/data/metrics.yml
+4-19Lines changed: 4 additions & 19 deletions
Original file line number
Diff line number
Diff line change
@@ -1144,6 +1144,10 @@ metrics:
1144
1144
help: Time in seek_fulfillment method including frontier checks and data collection.
1145
1145
source: src/compute/src/metrics.rs
1146
1146
visibility: internal
1147
+
- name: mz_index_peek_stashed_total
1148
+
help: The number of index peek walks that answered with a handle to the peek response stash, always a subset of the `offloaded` substrate of `mz_index_peek_walks_total`.
1149
+
source: src/compute/src/metrics.rs
1150
+
visibility: internal
1147
1151
- name: mz_index_peek_total_seconds_bucket
1148
1152
help: Time one visit to an index peek spent on the timely worker. A peek whose walk was offloaded contributes only the inline slice that offloaded it, and its time away from the worker is `mz_index_peek_offload_seconds`.
1149
1153
labels:
@@ -3704,25 +3708,6 @@ metrics:
3704
3708
- version
3705
3709
source: src/environmentd/src/environmentd/main.rs
3706
3710
visibility: internal
3707
-
- name: mz_stashed_peek_seconds_bucket
3708
-
help: Time spent reading a peek result and stashing it in the peek result stash (aka. persist blob).
3709
-
labels:
3710
-
- le
3711
-
- worker_id
3712
-
source: src/compute/src/metrics.rs
3713
-
visibility: internal
3714
-
- name: mz_stashed_peek_seconds_count
3715
-
help: Time spent reading a peek result and stashing it in the peek result stash (aka. persist blob).
3716
-
labels:
3717
-
- worker_id
3718
-
source: src/compute/src/metrics.rs
3719
-
visibility: internal
3720
-
- name: mz_stashed_peek_seconds_sum
3721
-
help: Time spent reading a peek result and stashing it in the peek result stash (aka. persist blob).
3722
-
labels:
3723
-
- worker_id
3724
-
source: src/compute/src/metrics.rs
3725
-
visibility: internal
3726
3711
- name: mz_statement_logging_actual_bytes
3727
3712
help: The total amount of SQL text that was logged by statement logging.
"The size, as number of rows, of each batch pumped from the peek result iterator (in one iteration through the worker loop) when stashing peek responses.",
643
-
ParameterScope::Environment,
644
-
);
645
-
646
629
/// Whether compute should stop peeks that iterate over too many rows.
"The maximum number of rows a peek may iterate over on each worker when enable_compute_peek_row_iteration_limit is enabled. Does not apply once a peek's results move to the peek stash.",
644
+
"The maximum number of rows a peek may iterate over on each worker when enable_compute_peek_row_iteration_limit is enabled. The count spans the peek's whole walk, rows written to the peek stash included.",
659
645
ParameterScope::Environment,
660
646
);
661
647
662
-
/// Whether a fast-path index peek may move its walk off the timely worker.
648
+
/// Whether a fast-path index peek may move its walk off the timely worker for latency.
663
649
///
664
-
/// Off, a peek walks to completion on the worker that owns it, delaying every other message that
665
-
/// worker serves. On, a peek that outruns [`INDEX_PEEK_INLINE_BUDGET`] finishes away from it.
650
+
/// Off, a peek walks on the worker that owns it until it answers, delaying every other message
651
+
/// that worker serves. On, a peek that outruns [`INDEX_PEEK_INLINE_BUDGET`] finishes away from it.
666
652
///
667
-
/// The kill switch for the whole mechanism, off by default until the path earns trust.
653
+
/// This gates latency offload only. A peek whose rows outgrow an inline answer is offloaded either
654
+
/// way, because the driver that writes to the peek stash is the offloaded one. Off means an ordinary
655
+
/// peek runs where it used to, not that none leaves the worker.
0 commit comments