Evidence that the consumption UI's "1 month" read is slow on Spanner, and why.
Instance meta-consumptiondb (chronosphere-production), database consumptionv1,
table AggregatedVolumes_60m (hourly rollup). Captured 2026-06-30.
The month view fires per-partition, stepped range reads over [monthStart, now] for
the metric SKU family. The query (01-live-ui-query.sql, verbatim from
SPANNER_SYS.QUERY_STATS) scans the hourly table — already the coarse table — yet
still reads millions of rows because of the fan-out:
128 shards × ~all partitions under global/ × ~720 hourly buckets × N resources
~15.5M rows scanned → ~37K returned, ~43 CPU-seconds, 10–12 s wall, recurring several
times per minute. Cloud Monitoring aggregate latency hides it (these are rare vs ~250M
point-reads/week); only per-query SPANNER_SYS exposes it.
Same shape, all 5 metric resources, run with --query-mode=PROFILE:
8.7M scanned, 37.6 CPU-s, 302 MB read, remote_server_calls: 382, locking_delay: 0.
The plan is a Distributed Cross Apply issuing a remote call per shard-split; the
sub-plan (scan AggregatedVolumes_60m → per-row SKU-weight CASE → per-shard hash
aggregate) runs once per split; a global hash-aggregate merges the partials. It is
CPU-bound distributed aggregation, not one sequential scan.
The reader/CLI path uses Spanner PRIORITY_LOW; the production gateway leaves priority
unspecified. Same query at each priority:
| priority | elapsed | cpu | server_queue_delay |
|---|---|---|---|
| unspecified (prod UI) | ~0.7–6 s | ~7–38 s | ~0.6–8 s |
| low (droidcli/jobs) | ~2–9 s | ~7–36 s | ~13 s |
Two independent costs: (1) fixed ~37–43 CPU-s of 128-way distributed hash-aggregation over millions of rows — the structural problem; (2) a low-priority queue delay that only the CLI/jobs path pays. Coarser tables can't help (already hourly). The fix is to kill the fan-out (shard-collapsed rollup / fewer shards) and/or columnar scan.