预降采样可以在数据写入时就按指定时间粒度对数据进行预计算并单独存储,降采样查询时可以自动查询匹配到的预降采样数据,以降低访问延迟。本文介绍预降采样的概念,创建和管理预降采样规则的方法,查询预降采样数据的方法,以及预降采样的最佳实践。
前提条件
时序引擎版本为3.4.19以上。
功能介绍
预降采样
预降采样是一种预计算的方法。在数据写入时根据配置的预降采样规则将数据降低精度后单独存储,查询时按查询条件中指定的降采样精度自动查询最接近预降采样精度的数据,然后交由执行引擎进行后续处理,以减少实时查询需要计算的数据量,降低访问延迟。
与连续查询相比,预降采样主要有以下优势:
写入即可见,无需连续查询的执行等待时间。
性能高,对于写入性能无影响,写入时实时转存数据。
预降采样数据和原始数据存储在同一张表中,预降采样查询时自动匹配最佳规则的数据,规则不匹配时,自动切换到原始数据查询。
预降采样规则
预降采样规则定义了预降采样的时间粒度和数据的聚合方式。例如,假设1分钟产生一条原始数据,预降采样规则可以定义按1小时数据的平均值进行预降采样。预降采样规则分为数据库级别的预降采样规则和表级别预降采样规则,它们都可以实现预降采样,但有部分区别,具体请参见下图。
创建预降采样规则
预降采样规则对于之前已经写入的数据不生效。
创建表级别的预降采样规则(SQL方式)
示例
设置预降采样精度为1小时,并对预降采样周期执行sum和max预计算。
CREATE PREDOWNSAMPLE `1h` AGGREGATORS (`sum`, `max`) ON sensor;
设置预降采样的数据有效期(TTL)为90天。
CREATE PREDOWNSAMPLE `1h` AGGREGATORS (`sum`, `max`) TTL `90d` ON sensor;
语法参考
创建数据库级别的预降采样规则(API方式)
请求路径和方法
请求路径 | 请求方法 | 描述 |
/api/database |
| 为指定数据库创建预降采样规则。 如果数据库已经存在(例如默认数据库default),请使用PUT方法来更新预降采样规则。 如果想在创建数据库时,同时创建预降采样规则,请使用POST方法。 |
请求参数
名称 | 是否必需 | 描述 |
name | 是 | 数据库名称。 例如:default。 |
downsampleRules | 是 | 预降采样规则列表,格式为JSON。每次更新规则时为全量更新。 |
预降采样规则参数
名称 | 是否必需 | 描述 | 举例 |
aggregator | 是 | 聚合函数。 取值:sum、count、max、min、first、last、median。 关于聚合函数的详情,请参见CREATE PREDOWNSAMPLE。 重要
| "aggregator": "sum" |
intervals | 是 | 预降采样的时间粒度列表,聚合时间窗口列表。支持的单位:s代表秒,m代表分钟,h代表小时,d代表天。 | "intervals": [ "10m","1h" ],表示按10分钟和1小时分别进行预降采样。 |
请求示例
PUT /api/database
{
"name": "default",
"downsampleRules": {
"rules": [
{
"aggregator": "sum",
"intervals": [
"1m",
"1h"
]
},
{
"aggregator": "max",
"intervals": [
"1m",
"1h"
]
}
]
}
}
响应说明
响应状态码为200。
查询预降采样规则
数据库级别的预降采样规则和表级别的预降采样规则的查询方法不同。数据库级别的预降采样规则需要通过API查询,表级别的预降采样规则需要通过SQL查询。
查询表级别的预降采样规则(SQL方式)
示例
查询数据库所有的预降采样规则。
SHOW PREDOWNSAMPLES;
查询指定数据表sensor的预降采样规则。
SHOW PREDOWNSAMPLES ON sensor;
语法参考
查询数据库级别的预降采样规则(API方式)
请求路径和方法
请求路径 | 请求方法 | 描述 |
/api/database | GET | 查询已经创建的预降采样规则。 |
返回示例
[{
"name": "default",
"downsampleRules": {
"rules": [
{
"aggregator": "sum",
"intervals": [
"1m",
"1h"
]
},
{
"aggregator": "max",
"intervals": [
"1m",
"1h"
]
}
]
}
}]
响应说明
响应状态码为204。
删除预降采样规则
数据库级别的预降采样规则和表级别的预降采样规则的删除方法不同。数据库级别的预降采样规则需要通过API删除,表级别的预降采样规则需要通过SQL删除。
删除预降采样规则后,已经生效的预降采样数据不会立即被删除,但在查询时不会命中已经删除的预降采样数据。预降采样的数据会在数据过期后(即超过TTL后)自动删除。
删除表级别的预降采样规则(SQL方式)
示例
DROP PREDOWNSAMPLE `1h` AGGREGATORS (`sum`, `max`) ON sensor;
语法参考
删除数据库级别的预降采样规则(API方式)
删除数据库级别的预降采样规则,请求路径、请求方法、请求参数和响应说明,与创建数据库级别的预降采样规则相同,区别为需要将downsampleRules的值置为空。请求路径等详细信息,请参见创建数据库级别的预降采样规则(API方式)。
请求示例
PUT /api/database
{
"name": "default",
"downsampleRules": {
}
}
查询预降采样数据
预降采样数据查询的匹配原则
当同时存在数据库级别规则和表级别规则时,预降采样查询数据时优先匹配表级别规则。
当查询请求指定的降采样粒度与预降采样数据的时间粒度不能精确匹配时,时序引擎会自动查询最优的预降采样粒度。推荐设置预降采样时间粒度为1m、10m、1h、1d,可以满足绝大多数的降采样查询场景。
说明最优的预降采样粒度是指能够整除查询请求的降采样粒度的最大值。例如,预降采样数据的时间粒度有1m、5m、8m和15m,查询请求的降采样粒度为10m,则最优预降采样粒度为5m。
当没有满足条件的预降采样时间粒度时,从原始数据中进行降采样查询。
查询方法
通过SQL或者兼容时间序列数据库TSDB的接口都可以查询预降采样数据。推荐使用SQL查询。如果是已有的openTSDB应用或时间序列数据库TSDB应用,可以选择TSDB兼容查询。
SQL查询预降采样数据
默认情况下,降采样查询数据是从原始数据中进行查询。如果要从预降采样数据中查询数据需要在查询语句中使用Hint(/*+ PREDOWNSAMPLE */)。
SELECT /*+ PREDOWNSAMPLE */ sum(temperature) from sensor
WHERE time >= 1619074800000 AND time <= 1619085600000
SAMPLE BY 1h;
TSDB兼容查询预降采样数据
兼容时间序列数据库TSDB的接口支持通过API多值查询、API单值查询、SDK查询三种方式查询预降采样数据。
SDK多值查询预降采样数据
查询降采样数据时,需要在MultiFieldSubQuery Builder设定downsampleDataSource参数。
示例
long startTime = 1619074800000L;
long endTime = 1619085600000L;
final String metric = "wind";
final String field = "speed";
MultiFieldSubQueryDetails fieldSubQueryDetails = MultiFieldSubQueryDetails
.field(field)
.aggregator(Aggregator.SUM)
.downsample("1h-sum")
.build();
MultiFieldSubQuery subQuery = MultiFieldSubQuery
.metric(metric)
.fieldsInfo(fieldSubQueryDetails)
// 从预降采样查询
.downsampleDataSource(DownsampleDataSource.DOWNSAMPLE)
.build();
MultiFieldQuery query = MultiFieldQuery.
start(startTime).
end(endTime).
sub(subQuery).
build();
List<MultiFieldQueryResult> result = tsdb.multiFieldQuery(query);
参数说明
DownsampleDataSource 参数的取值说明:
DOWNSAMPLE:预降采样数据查询。
RAW:原始数据查询。如果参数没有被指定,默认为RAW。
SDK多值的更多内容,请参见SDK多值读取。
API多值查询预降采样数据
使用API进行多值查询时,添加downsampleSource参数并定义参数为downsample,即可查询预降采样数据。具体操作,请参见多值数据查询。
请求路径和方法
请求路径 | 请求方法 | 描述 |
/api/mquery | GET | 查询预降采样数据。 |
请求参数
名称 | 是否必须 | 描述 | 示例 |
downsampleSource | 否 | 指定查询数据源。取值:
| downsample |
请求示例
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"
}
}
]
}
预降采样的最佳配置
秒级采样频率场景
对于秒级采样频率的场景,推荐配置1m、1h、1d粒度的预降采样规则来满足任意分钟、任意小时、任意天级别的降采样查询需求。
预降采样规则的示例
配置sum、count、min、max4种常用聚合函数在1m、1h、1d粒度的预降采样规则。
CREATE PREDOWNSAMPLE `1m` AGGREGATORS (`sum`, `count`, `min`, `max`) ON sensor;
CREATE PREDOWNSAMPLE `1h` AGGREGATORS (`sum`, `count`, `min`, `max`) ON sensor;
CREATE PREDOWNSAMPLE `1d` AGGREGATORS (`sum`, `count`, `min`, `max`) ON sensor;
预降采样查询的示例
基于分钟粒度的预降采样规则,满足任意分钟级别的降采样查询。
SELECT /*+ PREDOWNSAMPLE */ sum(temperature), max(temperature) FROM sensor WHERE time >= 1619074800000 AND time <= 1619085600000 SAMPLE BY <N>m;
基于小时粒度的预降采样规则,满足任意小时级别的降采样查询。
SELECT /*+ PREDOWNSAMPLE */ sum(temperature), max(temperature) FROM sensor WHERE time >= 1619074800000 AND time <= 1619085600000 SAMPLE BY <N>h;
基于天粒度的预降采样规则,满足任意天级别的降采样查询。
SELECT /*+ PREDOWNSAMPLE */ sum(temperature), max(temperature) FROM sensor WHERE time >= 1619074800000 AND time <= 1619600400000 SAMPLE BY <N>d;
分钟级采样频率场景
对于分钟级采样频率的场景,推荐配置1h、1d粒度的预降采样规则来满足任意小时、任意天级别的降采样查询需求。
预降采样规则的示例
配置sum、count、min、max4种常用聚合函数在1h、1d粒度的预降采样规则。
CREATE PREDOWNSAMPLE `1h` AGGREGATORS (`sum`, `count`, `min`, `max`) ON sensor;
CREATE PREDOWNSAMPLE `1d` AGGREGATORS (`sum`, `count`, `min`, `max`) ON sensor;
预降采样查询的示例
基于小时粒度的预降采样规则,满足任意小时级别的降采样查询。
SELECT /*+ PREDOWNSAMPLE */ sum(temperature), max(temperature) FROM sensor WHERE time >= 1619074800000 AND time <= 1619085600000 SAMPLE BY <N>h;
基于天粒度的预降采样规则,满足任意天级别的降采样查询。
SELECT /*+ PREDOWNSAMPLE */ sum(temperature), max(temperature) FROM sensor WHERE time >= 1619074800000 AND time <= 1619600400000 SAMPLE BY <N>d;