Pre-downsampling pre-aggregates time series data as it is written to LindormTSDB, so downsampling queries automatically hit the pre-aggregated results instead of scanning raw data. This reduces query latency without affecting write performance.
Compared with continuous queries, pre-downsampling offers the following additional benefits:
Immediately queryable. Pre-downsampled data can be queried as soon as it is written — no waiting for continuous query execution.
Same-table storage. Pre-downsampled data and raw data are stored in the same table. If the pre-downsampled data does not match the rule specified in a query, raw data is queried automatically.
Prerequisites
Before you begin, ensure that:
The LindormTSDB version of your Lindorm instance is 3.4.19 or later.
To check or upgrade the LindormTSDB version, see Release notes of LindormTSDB and Upgrade the minor engine version of a Lindorm instance.
How it works
Consider an IoT scenario where a sensor writes one temperature reading per second. When you run a query aggregated at one-hour intervals, LindormTSDB would normally scan every raw data point in the time range. With pre-downsampling, LindormTSDB computes the aggregates as data arrives and stores them separately. The query engine then reads the pre-aggregated results directly, processing far less data.
Pre-downsampling rules define what gets pre-aggregated: the time granularity (for example, 1 hour) and the aggregate functions (for example, sum and max). Rules are scoped to either a table or a database.
When a downsampling query runs, LindormTSDB selects the pre-aggregated dataset whose interval is the largest divisor of the query interval. For example, if data is pre-downsampled at 1m, 5m, 8m, and 15m, and the query uses a 10m interval, the 5m pre-downsampled data is used. If no pre-downsampled data matches, raw data is queried instead.
If rules are configured for both a database and a table in that database, the table-level rules take precedence.
Create a pre-downsampling rule
A pre-downsampling rule applies only to data written to the table or database after the rule is created.
Create a rule for a table (SQL)
Use CREATE PREDOWNSAMPLE to define a rule on a specific table.
Example 1: Pre-downsample at 1-hour intervals using sum and max.
CREATE PREDOWNSAMPLE `1h` AGGREGATORS (`sum`, `max`) ON sensor;Example 2: Pre-downsample at 1-hour intervals with a 90-day TTL on the pre-aggregated data.
CREATE PREDOWNSAMPLE `1h` AGGREGATORS (`sum`, `max`) TTL `90d` ON sensor;For full syntax, see CREATE PREDOWNSAMPLE.
Create a rule for a database (API)
Use the /api/database endpoint to configure pre-downsampling rules for an entire database. Each update replaces all existing rules for the database.
Request path and method
| Request path | Method | Description |
|---|---|---|
/api/database | POST | Create a new database with pre-downsampling rules. |
/api/database | PUT | Update pre-downsampling rules for an existing database. |
Request parameters
| Parameter | Required | Description |
|---|---|---|
name | Yes | The database name. Example: default. |
downsampleRules | Yes | The list of pre-downsampling rules. Each update replaces all rules in the list. |
Parameters for each rule in downsampleRules.rules:
| Parameter | Required | Description | Example |
|---|---|---|---|
aggregator | Yes | The aggregate function. Valid values: sum, count, max, min, first, last, median. See Aggregator notes. | "aggregator": "sum" |
intervals | Yes | The time intervals for pre-downsampling. Supported units: s (second), m (minute), h (hour), d (day). | ["10m", "1h"] |
Aggregator notes
The avg function is not supported. To compute averages, configure both count and sum — LindormTSDB uses these to calculate average values automatically.
If data is repeatedly overwritten, computed averages may be inaccurate. Use this approach only when no data is overwritten during pre-downsampling.
Sample request
PUT /api/database{
"name": "default",
"downsampleRules": {
"rules": [
{
"aggregator": "sum",
"intervals": ["1m", "1h"]
},
{
"aggregator": "max",
"intervals": ["1m", "1h"]
}
]
}
}A successful request returns HTTP status code 200.
Query pre-downsampling rules
Query rules for a table (SQL)
-- Query rules for all tables in the current database
SHOW PREDOWNSAMPLES;
-- Query rules for a specific table
SHOW PREDOWNSAMPLES ON sensor;For full syntax, see SHOW PREDOWNSAMPLES.
Query rules for a database (API)
GET /api/databaseSample response
[{
"name": "default",
"downsampleRules": {
"rules": [
{
"aggregator": "sum",
"intervals": ["1m", "1h"]
},
{
"aggregator": "max",
"intervals": ["1m", "1h"]
}
]
}
}]A successful request returns HTTP status code 204.
Delete a pre-downsampling rule
Deleting a rule does not immediately remove pre-aggregated data. Existing pre-aggregated data is excluded from query results and is deleted automatically when it expires based on TTL.
Delete rules for a table (SQL)
DROP PREDOWNSAMPLE `1h` AGGREGATORS (`sum`, `max`) ON sensor;For full syntax, see DROP PREDOWNSAMPLE.
Delete rules for a database (API)
Send the same PUT /api/database request used to create rules, but set downsampleRules to an empty object.
PUT /api/database{
"name": "default",
"downsampleRules": {}
}A successful request returns HTTP status code 200.
Query pre-downsampled data
Use SQL
Add the /*+ PREDOWNSAMPLE */ hint to route the query to pre-aggregated data. Without this hint, the query reads raw data.
-- Route to pre-aggregated data using the PREDOWNSAMPLE hint
SELECT /*+ PREDOWNSAMPLE */ sum(temperature)
FROM sensor
WHERE time >= 1619074800000 AND time <= 1619085600000
SAMPLE BY 1h;Use TSDB-compatible methods
You can use API-based multi-value queries, API-based single-value queries, and SDKs to query pre-downsampled data.
Use the SDK
Set DownsampleDataSource to DOWNSAMPLE in the MultiFieldSubQuery builder.
long startTime = 1619074800000L;
long endTime = 1619085600000L;
MultiFieldSubQueryDetails fieldSubQueryDetails = MultiFieldSubQueryDetails
.field("speed")
.aggregator(Aggregator.SUM)
.downsample("1h-sum") // Downsample interval and aggregate function
.build();
MultiFieldSubQuery subQuery = MultiFieldSubQuery
.metric("wind")
.fieldsInfo(fieldSubQueryDetails)
.downsampleDataSource(DownsampleDataSource.DOWNSAMPLE) // Use pre-downsampled data
.build();
MultiFieldQuery query = MultiFieldQuery
.start(startTime)
.end(endTime)
.sub(subQuery)
.build();
List<MultiFieldQueryResult> result = tsdb.multiFieldQuery(query);DownsampleDataSource values:
| Value | Description |
|---|---|
DOWNSAMPLE | Query pre-downsampled data. |
RAW | Query raw data. This is the default. |
For more information, see Use the SDK multi-value data model to read data.
Use the API (multi-value query)
Add downsampleSource: "downsample" to the query body to read pre-aggregated data.
Request path and method
| Request path | Method | Description |
|---|---|---|
/api/mquery | POST | Query pre-downsampled data. |
Request parameters
| Parameter | Required | Description | Example |
|---|---|---|---|
downsampleSource | No | The data source. downsample: pre-downsampled data. raw: raw data (default). | downsample |
Sample request
POST /api/mquery{
"start": 1346846400000,
"end": 1346846402000,
"queries": [
{
"downsampleDataSource": "downsample",
"metric": "wind",
"fields": [
{
"field": "speed",
"aggregator": "none",
"downsample": "1h-sum"
}
],
"tags": {
"sensor": "IOTE_8859_0002"
}
}
]
}For more information, see Query a multivariate data point.
Best practices
Considerations
Before configuring pre-downsampling, keep the following in mind:
Rules apply to future data only. Data written before a rule is created is not pre-downsampled. Apply rules before data ingestion if possible.
Fallback to raw data. If no pre-downsampled data matches the query interval, LindormTSDB automatically falls back to raw data.
The
avgfunction is not supported. Configuresumandcountinstead; LindormTSDB uses them to compute averages automatically.Deleted rule data expires naturally. After you delete a rule, its pre-aggregated data is excluded from results and removed when its TTL expires.
Set recommended intervals. Configure intervals at 1m, 10m, 1h, or 1d to cover most downsampling query patterns.
Pre-downsampling for second-level data
For data sampled every second, configure rules at 1-minute, 1-hour, and 1-day intervals. This multi-level structure lets queries at any minute, hour, or day granularity hit pre-aggregated data rather than raw rows.
Create rules
-- Level 1: aggregate raw (per-second) data into 1-minute summaries
CREATE PREDOWNSAMPLE `1m` AGGREGATORS (`sum`, `count`, `min`, `max`) ON sensor;
-- Level 2: aggregate into 1-hour summaries
CREATE PREDOWNSAMPLE `1h` AGGREGATORS (`sum`, `count`, `min`, `max`) ON sensor;
-- Level 3: aggregate into 1-day summaries
CREATE PREDOWNSAMPLE `1d` AGGREGATORS (`sum`, `count`, `min`, `max`) ON sensor;Query examples
-- Any-minute interval query — uses the 1m pre-downsampled data
SELECT /*+ PREDOWNSAMPLE */ sum(temperature), max(temperature)
FROM sensor
WHERE time >= 1619074800000 AND time <= 1619085600000
SAMPLE BY <N>m;
-- Any-hour interval query — uses the 1h pre-downsampled data
SELECT /*+ PREDOWNSAMPLE */ sum(temperature), max(temperature)
FROM sensor
WHERE time >= 1619074800000 AND time <= 1619085600000
SAMPLE BY <N>h;
-- Any-day interval query — uses the 1d pre-downsampled data
SELECT /*+ PREDOWNSAMPLE */ sum(temperature), max(temperature)
FROM sensor
WHERE time >= 1619074800000 AND time <= 1619600400000
SAMPLE BY <N>d;Pre-downsampling for minute-level data
For data sampled every minute, configure rules at 1-hour and 1-day intervals. Minute-level granularity queries read raw data directly, so only coarser intervals need pre-downsampling.
Create rules
-- Aggregate per-minute data into 1-hour summaries
CREATE PREDOWNSAMPLE `1h` AGGREGATORS (`sum`, `count`, `min`, `max`) ON sensor;
-- Aggregate into 1-day summaries
CREATE PREDOWNSAMPLE `1d` AGGREGATORS (`sum`, `count`, `min`, `max`) ON sensor;Query examples
-- Any-hour interval query — uses the 1h pre-downsampled data
SELECT /*+ PREDOWNSAMPLE */ sum(temperature), max(temperature)
FROM sensor
WHERE time >= 1619074800000 AND time <= 1619085600000
SAMPLE BY <N>h;
-- Any-day interval query — uses the 1d pre-downsampled data
SELECT /*+ PREDOWNSAMPLE */ sum(temperature), max(temperature)
FROM sensor
WHERE time >= 1619074800000 AND time <= 1619600400000
SAMPLE BY <N>d;