Skip to content

Conversation

@dnhatn
Copy link
Member

@dnhatn dnhatn commented Nov 23, 2025

This change adds support for window functions for additional time-series aggregations, including min_over_time, max_over_time, first_over_time, count_over_time, and sum_over_time. These changes are straightforward. The main update in this PR is how the window is expanded before sliding over the partial results.

For example, given these data points:

|_tsid| cluster| host | timestamp            | metric |
| t1  | prod   | h1   | 2025-04-15T01:12:00Z | 100    |
| t2  | prod   | h2   | 2025-04-15T01:14:00Z | 200    |

With bucket=5s and no window:

TS ...
| WHERE TRANGE('2025-04-15T01:10:00Z', '2025-04-15T01:15:00Z')
| STATS sum(sum_over_time(metric)) BY host, TBUCKET(5s)

Yields:

cluster | bucket                 | SUM  | 
prod    | 2025-04-15T01:10:00Z   | 300  |

With a window=5s:

TS ...
| WHERE TRANGE('2025-04-15T01:10:00Z', '2025-04-15T01:15:00Z')
| STATS sum(sum_over_time(metric, 5s)) BY host, TBUCKET(1s)

Yields:

cluster | bucket                 | SUM  | 
prod    | 2025-04-15T01:12:00Z   | 100  |
prod    | 2025-04-15T01:14:00Z   | 200  |

Ideally, all buckets from 2025-04-15T01:10:00Z to 2025-04-15T01:14:00Z should be generated:

cluster | bucket                 | SUM  | 
prod    | 2025-04-15T01:10:00Z   | 300  |
prod    | 2025-04-15T01:11:00Z   | 300  |
prod    | 2025-04-15T01:12:00Z   | 300  |
prod    | 2025-04-15T01:13:00Z   | 300  |
prod    | 2025-04-15T01:14:00Z   | 300  |

With this change, buckets are expanded as if sliding over the raw input before combining for the final results.

@dnhatn dnhatn added >non-issue :StorageEngine/ES|QL Timeseries / metrics / logsdb capabilities in ES|QL v9.3.0 labels Nov 23, 2025
@github-actions
Copy link
Contributor

ℹ️ Important: Docs version tagging

👋 Thanks for updating the docs! Just a friendly reminder that our docs are now cumulative. This means all 9.x versions are documented on the same page and published off of the main branch, instead of creating separate pages for each minor version.

We use applies_to tags to mark version-specific features and changes.

Expand for a quick overview

When to use applies_to tags:

✅ At the page level to indicate which products/deployments the content applies to (mandatory)
✅ When features change state (e.g. preview, ga) in a specific version
✅ When availability differs across deployments and environments

What NOT to do:

❌ Don't remove or replace information that applies to an older version
❌ Don't add new information that applies to a specific version without an applies_to tag
❌ Don't forget that applies_to tags can be used at the page, section, and inline level

🤔 Need help?

@dnhatn dnhatn force-pushed the more-window-function-1 branch from b6f0988 to b07352b Compare November 23, 2025 06:02
@dnhatn dnhatn force-pushed the more-window-function-1 branch from b07352b to 1c43338 Compare November 23, 2025 06:09
@dnhatn dnhatn requested a review from kkrik-es November 24, 2025 06:03
@dnhatn dnhatn marked this pull request as ready for review November 24, 2025 06:03
@elasticsearchmachine
Copy link
Collaborator

Pinging @elastic/es-storage-engine (Team:StorageEngine)

* 02:00 -> [12:00, 13:59) // bucket=2m
* 00:04 -> [04:00, 05:59), [06:00, 07:59), [08:00, 09:59), [10:00, 11:59), [12:00, 13:59) // window=10m
*/
private void expandWindowBuckets() {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@kkrik-es This is the main change

* For example, if the window is 10 minutes and the bucket size is 2 minutes:
* If we see a bucket at 12:00, we need to ensure buckets exist for the previous 10 minutes.
* 02:00 -> [12:00, 13:59) // bucket=2m
* 00:04 -> [04:00, 05:59), [06:00, 07:59), [08:00, 09:59), [10:00, 11:59), [12:00, 13:59) // window=10m
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm somewhat confused by these examples - while the text above is clear. Shouldn't we have an example where, at 12:00, we need to include data from 11:50 and on?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will update the comment; the PR description may provide more clarity.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right that example was nice.

long endTimestamp = tsBlockHash.getLongKeyFromGroup(groupId);
long bucket = timeBucket.nextRoundingValue(endTimestamp - timeResolution.convert(largestWindowMillis()));
bucket = Math.max(bucket, tsBlockHash.getMinLongKey());
while (bucket < endTimestamp) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: consider adding a comment here, we're filling in missing buckets due to the window expanding outside each bucket.

Copy link
Contributor

@kkrik-es kkrik-es left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice, makes sense.

@dnhatn
Copy link
Member Author

dnhatn commented Nov 24, 2025

Thanks Kostas!

@dnhatn dnhatn merged commit ff33b6c into elastic:main Nov 24, 2025
34 checks passed
@dnhatn dnhatn deleted the more-window-function-1 branch November 24, 2025 20:38
afoucret pushed a commit to afoucret/elasticsearch that referenced this pull request Nov 26, 2025
This change adds support for window functions for additional time-series 
aggregations, including `min_over_time`, `max_over_time`,
`first_over_time`, `count_over_time`, and `sum_over_time`. These changes
are straightforward. The main update in this PR is how the window is
expanded before sliding over the partial results.

For example, given these data points:

```
|_tsid| cluster| host | timestamp            | metric |
| t1  | prod   | h1   | 2025-04-15T01:12:00Z | 100    |
| t2  | prod   | h2   | 2025-04-15T01:14:00Z | 200    |
```

With `bucket=5s` and no window:

```
TS ...
| WHERE TRANGE('2025-04-15T01:10:00Z', '2025-04-15T01:15:00Z')
| STATS sum(sum_over_time(metric)) BY host, TBUCKET(5s)
```

Yields:

```
cluster | bucket                 | SUM  |
prod    | 2025-04-15T01:10:00Z   | 300  |
```

With a window=5s:

```
TS ...
| WHERE TRANGE('2025-04-15T01:10:00Z', '2025-04-15T01:15:00Z')
| STATS sum(sum_over_time(metric, 5s)) BY host, TBUCKET(1s)
```

Yields:

```
cluster | bucket                 | SUM  |
prod    | 2025-04-15T01:12:00Z   | 100  |
prod    | 2025-04-15T01:14:00Z   | 200  |
```

Ideally, all buckets from `2025-04-15T01:10:00Z` to 
`2025-04-15T01:14:00Z` should be generated:

```
cluster | bucket                 | SUM  | 
prod    | 2025-04-15T01:10:00Z   | 300  |
prod    | 2025-04-15T01:11:00Z   | 300  |
prod    | 2025-04-15T01:12:00Z   | 300  |
prod    | 2025-04-15T01:13:00Z   | 200  |
prod    | 2025-04-15T01:14:00Z   | 200  |
```

With this change, buckets are expanded as if sliding over the raw input 
before combining for the final results.
ncordon pushed a commit to ncordon/elasticsearch that referenced this pull request Nov 26, 2025
This change adds support for window functions for additional time-series 
aggregations, including `min_over_time`, `max_over_time`,
`first_over_time`, `count_over_time`, and `sum_over_time`. These changes
are straightforward. The main update in this PR is how the window is
expanded before sliding over the partial results.

For example, given these data points:

```
|_tsid| cluster| host | timestamp            | metric |
| t1  | prod   | h1   | 2025-04-15T01:12:00Z | 100    |
| t2  | prod   | h2   | 2025-04-15T01:14:00Z | 200    |
```

With `bucket=5s` and no window:

```
TS ...
| WHERE TRANGE('2025-04-15T01:10:00Z', '2025-04-15T01:15:00Z')
| STATS sum(sum_over_time(metric)) BY host, TBUCKET(5s)
```

Yields:

```
cluster | bucket                 | SUM  |
prod    | 2025-04-15T01:10:00Z   | 300  |
```

With a window=5s:

```
TS ...
| WHERE TRANGE('2025-04-15T01:10:00Z', '2025-04-15T01:15:00Z')
| STATS sum(sum_over_time(metric, 5s)) BY host, TBUCKET(1s)
```

Yields:

```
cluster | bucket                 | SUM  |
prod    | 2025-04-15T01:12:00Z   | 100  |
prod    | 2025-04-15T01:14:00Z   | 200  |
```

Ideally, all buckets from `2025-04-15T01:10:00Z` to 
`2025-04-15T01:14:00Z` should be generated:

```
cluster | bucket                 | SUM  | 
prod    | 2025-04-15T01:10:00Z   | 300  |
prod    | 2025-04-15T01:11:00Z   | 300  |
prod    | 2025-04-15T01:12:00Z   | 300  |
prod    | 2025-04-15T01:13:00Z   | 200  |
prod    | 2025-04-15T01:14:00Z   | 200  |
```

With this change, buckets are expanded as if sliding over the raw input 
before combining for the final results.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

>non-issue :StorageEngine/ES|QL Timeseries / metrics / logsdb capabilities in ES|QL Team:StorageEngine v9.3.0

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants