Tdengine流式计算实现聚合查询

概要

之前业务需要实现聚合查询,使用taos流式计算实现,本文记录其中流式计算中遇到的坑。

流式计算概念

流式计算(Stream Processing),也称为实时流计算,是一种计算模式,它能够对连续生成的数据流进行实时处理和分析。与传统的批处理(Batch Processing)模式不同,流式计算不需要等待所有数据到齐后才开始处理,而是以数据产生为驱动,边接收数据边进行处理。
多用于物联网,金融等大量连续数据处理中

例如数采软件,近期数据存储原始数据,同时通过流式计算存储聚合数据,过期时删除原始数据,只查询聚合数据即可大大降低数据量

Taos流式计算语句

1.创建流式运算语句

CREATE STREAM [IF NOT EXISTS] stream_name [stream_options] INTO stb_name[(field1_name, ...)] [TAGS (create_definition [, create_definition] ...)] SUBTABLE(expression) AS subquery

其中stream_options中的参数为

stream_options: {
 TRIGGER        [AT_ONCE | WINDOW_CLOSE | MAX_DELAY time]
 WATERMARK      time
 IGNORE EXPIRED [0|1]
 DELETE_MARK    time
 FILL_HISTORY   [0|1]
 IGNORE UPDATE  [0|1]
}

TRIGGER:触发器,设置什么时候触发流式计算
WATERMARK:水印,判断时间戳是否已经计算
IGNORE_EXPIRED:是否忽略过期数据
DELETE_MARK:删除时间标记,超时自动删除
FILL_HISTORY:是否启动流式时计算历史数据
IGNORE_UPDATE:是否忽略修改数据

其中subquery的参数为

subquery: SELECT select_list
    from_clause
    [WHERE condition]
    [PARTITION BY tag_list]
    [window_clause]

subquery代表了定义的流式查询语句

创建聚合库

上面简单介绍了流式查询语句,下面根据聚合时间规划数据库
数据库 DATABASE_6M:用来存储6小时、1天、7天聚合
数据库 DATABASE_1Y:用来存储1月聚合

创建6小时聚合流语句

CREATE STREAM IF NOT EXISTS STREAM_6h fill_history 1 INTO DATABASE_6M.TABLE_NUMERICAL_6h SUBTABLE(CONCAT('p_6h_',id)) AS  SELECT _WSTART AS TS, MAX(POINTVALUE) AS MAX_VALUE ,MIN(POINTVALUE) AS MIN_VALUE, AVG(POINTVALUE) AS AVG_VALUE, FIRST(POINTVALUE) AS FIRST_VALUE, LAST(POINTVALUE) AS LAST_VALUE, APERCENTILE(POINTVALUE,50) AS APERCENTILE_VALUE, COUNT(POINTVALUE) AS COUNT_VALUE FROM DATABASE_3M.TABLE_NUMERICAL PARTITION BY EQPID ID  INTERVAL(6h) 

该语句创建STREAM_6h流,同时计算历史数据,定义了子表的命名规则为p_6h_加pid,间隔6小时
通过之前实现的createStream方法创建流

    @Override
    public void initStream() {
        //原始数据数据库名
        String originSource = TDengineDatabaseParamEnums.MONTH_THREE.getDatabaseName() + "." + TDengineConstants.TABLE_NUMERICAL_NAME;
        TDengineDatabaseParamEnums[] values = TDengineDatabaseParamEnums.values();
        for (TDengineDatabaseParamEnums value : values) {
            String databaseName = value.getDatabaseName();
            if (databaseName.equals(TDengineDatabaseParamEnums.MONTH_THREE.getDatabaseName())) {
                continue;
            }
            //原始数据源
            List<String> aggregateTimeList = StringUtil.getAggregateTimeByDatabaseName(databaseName);
            aggregateTimeList.forEach(aggregateTime -> {
                String streamName = TDengineConstants.STREAM_NAME_PREFIX + aggregateTime;
                String stbName = TDengineConstants.STREAM_TABLE_PREFIX + aggregateTime;
                //查询内容
                String subquery = StrUtil.format(TDengineSqlConstants.STREAM_SUBQUERY, originSource, aggregateTime);
                createStream(streamName, null, stbName, subquery);
            });
        }
    }

具体实现详见上篇文章Tdneing整合MybatisPlus

创建完成后结构如下在这里插入图片描述

获取聚合数据

1.创建聚合结构实体

@EqualsAndHashCode(callSuper = true)
@Data
@TableName("table_numerical_6h.table_numerical_6h;")
public class TableNumerical extends BaseTaosModel<TableNumerical> {

    @ApiModelProperty("最大值")
    private Float maxValue;

    @ApiModelProperty("最小值")
    private Float minValue;

    @ApiModelProperty("平均值")
    private Double avgValue;

    @ApiModelProperty("开始值")
    private Float firstValue;

    @ApiModelProperty("结束值")
    private Float lastValue;

    @ApiModelProperty("中位数")
    private Double apercentileValue;

    @ApiModelProperty("总数")
    private Long countValue;

    @ApiModelProperty("groupId")
    private Long groupId;
}

其余文件省略,查询时根据条件查询即可,示例如下

    public void test(){
        Timestamp startTime = Timestamp.valueOf(LocalDateTime.now());
        Timestamp endTime = Timestamp.valueOf(LocalDateTime.now().plusDays(1));
        // 查询子表为4617573834247140801的今天的数据,聚合6小时
        List<TableNumerical> list = tableNumericalService.lambdaQuery()
                .eq(TableNumerical::getGroupId, "4617573834247140801")
                .le(TableNumerical::getTs, endTime)
                .ge(TableNumerical::getTs, startTime)
                .list();
    }

总结

到此,聚合查询实现完毕,最好结合上一篇MybatisPlus整合观看,其中stream_options参数最好根据实际结构决定,本结构用于处理历史数据,所以使用了FILL_HISTORY参数,但是流式计算占用硬盘和内存非常高,暂未测试此参数和taos版本与服务器硬件关联

  • 12
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值