summarize
Groups rows and calculates aggregate values over each group.
Without a by clause, aggregates all rows into a single result.
Aggregate state is held in memory and merged at the coordinator before any result is produced, so it grows with group cardinality, time-bin count, and per-aggregate state (percentile sketches, make_set/make_list, histogram snapshots). To stay safe under load, every summarize runs under a per-operator memory budget. When a query exceeds it, the engine degrades rather than failing or running out of memory: it keeps a representative subset of series (the non-time group-key values), preserving every time bin of each surviving series so timecharts never get holes, and attaches a coverage warning reporting the estimated fraction of series retained. When there is no series axis (for example grouping by bin(timestamp, …) alone), each group counts as its own series: whole groups are dropped, the same ones on every worker, with the same coverage warning. Only a summarize with no by at all has nothing to drop and fails with an actionable error. Use hint.budget and hint.sample to tune this per query.
The budget covers everything a summarize holds: each group's key and bookkeeping as well as its aggregate state. A state holds at most seven eighths of what a query process may send at once (an eighth of its memory, 64 MiB to 1 GiB), whatever its budget. The group keys are also bounded by a dictionary of their own: past it, the default hint.sample=sample samples series the same way, and otherwise the result is truncated with a warning.
All of a query's aggregate state is also capped together, per query and per process (by default half the process memory limit), since a query holds many operator states at once. Over that cap the query samples its series the same way, at one cutoff shared by all its states, or fails when it has no group-by key. hint.budget, including hint.budget=max, raises only the per-operator budget, never this cap.
Syntax
summarize aggregation, ...Aggregate all rows
Parameters
| Name | Description |
|---|---|
| aggregation | Aggregation function (count(), sum(), avg(), etc.), or a residual expression that names single-output aggregate columns without itself calling an aggregate (b = max_timestamp + 1h). A repeated max(timestamp) is max_timestamp, then max_timestamp1. |
Syntax
summarize aggregation, ... by column, ...Aggregate grouped by columns
Parameters
| Name | Description |
|---|---|
| aggregation | Aggregation function (count(), sum(), avg(), etc.), or a residual expression that names single-output aggregate columns without itself calling an aggregate (b = max_timestamp + 1h). A repeated max(timestamp) is max_timestamp, then max_timestamp1. |
| column | Column or expression to group by |
Syntax
summarize [hint.sample=strategy] [hint.budget=size] aggregation, ... by column, ...Tune the per-operator memory budget and the strategy used to shed state when it is exceeded. Hints appear immediately after summarize, before the aggregations.
Parameters
| Name | Description |
|---|---|
| hint.budget | Per-operator memory ceiling — a byte count (e.g. 67108864), a quoted binary size (e.g. "64mib"), or max (clamped to the deployment maximum). Lower to tighten, raise to loosen up to the deploy cap. It covers group keys and bookkeeping as well as aggregate state, and the deployment's transport limit caps it too. |
| (optional) |
hint.sample=
Which series to keep when the budget is exceeded (whole series are dropped; time bins are always preserved).
| Value | Description |
|---|---|
sample | Bottom-K by a stable hash of the series key (default). Keeps the series with the smallest hashes, so the sample is representative and reruns keep nearly the same series. |
heaviest | Keep the heaviest series by weight, dropping the lightest first. |
Examples
Example 1
datatable(clan:string, warrior:string, battles:long)[
"Ragnarsson", "Bjorn", 15,
"Ragnarsson", "Ivar", 22,
"Ragnarsson", "Sigurd", 8,
"Lothbrok", "Ragnar", 30,
"Lothbrok", "Lagertha", 18,
"Fairhair", "Harald", 25,
"Fairhair", "Halfdan", 12
]
| summarize total_battles = sum(battles), warriors = count(), best = max(battles) by clan| clan (string) | total_battles (long) | warriors (long) | best (long) |
|---|---|---|---|
| Fairhair | 37 | 2 | 25 |
| Lothbrok | 48 | 2 | 30 |
| Ragnarsson | 45 | 3 | 22 |
Example 2
datatable(weapon:string, warrior:string)[
"axe", "Ragnar",
"sword", "Bjorn",
"axe", "Ivar",
"spear", "Lagertha",
"axe", "Floki",
"sword", "Harald"
]
| summarize count() by weapon| weapon (string) | count_ (long) |
|---|---|
| axe | 3 |
| spear | 1 |
| sword | 2 |
Example 3
datatable(region:string, raid:string, silver:long)[
"England", "Lindisfarne", 500,
"Francia", "Paris", 7000,
"England", "York", 1200,
"Francia", "Rouen", 3000,
"England", "Winchester", 300
]
| summarize total_silver = sum(silver), raids = count() by region| region (string) | total_silver (long) | raids (long) |
|---|---|---|
| England | 2000 | 3 |
| Francia | 10000 | 2 |
Example 4
datatable(warrior:string, voyages:long)[
"Ragnar", 42,
"Bjorn", 31,
"Ivar", 35,
"Lagertha", 28,
"Harald", 25
]
| summarize avg(voyages), max(voyages), min(voyages)| avg_voyages (real) | max_voyages (long) | min_voyages (long) |
|---|---|---|
| 32.2 | 42 | 25 |
Example 5 — Set the per-operator memory budget with hint.budget (a generous budget here, so the result is exact)
datatable(route:string, duration_ms:long)[
"/checkout", 120,
"/checkout", 340,
"/checkout", 95,
"/cart", 60,
"/cart", 80,
"/search", 200,
"/search", 410,
"/search", 150
]
| summarize hint.budget = "64mib" p95 = percentile(duration_ms, 95) by route| route (string) | p95 (real) |
|---|---|
| /cart | 80.64818822153299 |
| /checkout | 340.4078108381472 |
| /search | 407.54458708462647 |
Example 6 — Choose the strategy used to shed series if the budget is exceeded — heaviest keeps the highest-weight series
datatable(service:string, region:string, latency:long)[
"api", "eu", 120,
"api", "us", 90,
"web", "eu", 200,
"web", "us", 150,
"db", "eu", 30,
"db", "us", 45
]
| summarize hint.sample = heaviest hint.budget = "32mib" requests = count(), p95 = percentile(
latency,
95
)
by service| service (string) | requests (long) | p95 (real) |
|---|---|---|
| api | 2 | 120.31456328864437 |
| db | 2 | 45.153915815167686 |
| web | 2 | 198.3684859812456 |