连续查询是一种简化的流计算能力,能够定期执行SQL查询,将查询结果存储在指定的数据表中,可用于预降采样和预计算,实现数据降精度长期存储以及查询性能提升。本文介绍Lindorm时序引擎连续查询的概念、使用方法和常见场景。
背景信息
在时序应用的场景下,对于依照时间顺序写入的实时数据,用户有时会希望每隔一段固定时间,就能够按照一定的查询条件对该时间范围内的时序数据进行一次计算(例如:对该时间范围内的数据进行一次聚合计算),并将计算结果另行保存下来。连续查询所针对的便是此类应用场景。
场景示例如下:
连续查询的概念
连续查询(Continuous Queries,简称CQ)提供了一种简化的流计算能力,自动定期执行时序SQL查询, 将查询结果存储在指定的数据表中。
连续查询会每隔一段时间(Interval)对一个时间窗口(Window)的数据进行计算。
例如,一个连续查询指定的计算间隔(Interval)和时间窗口(Window)均为1小时,该连续查询会在每个小时开始的时候对前一小时的数据进行计算。如果晚上20:00触发计算,计算的数据所属时间范围是[19:00:00,20:00:00)
。
连续查询会指定的计算间隔后立刻开始计算,但由于查询计算量的不同,计算的结果可能也需要花一些时间才能保存到目标表中。延时取决于查询计算量以及实例的实时负载。
连续查询的结果精度取决于原始数据的有序性。如果数据未按照时间顺序写入原始数据表,即下一个时间窗口开始后仍然有上一时间窗口的数据零星写入,连续查询不会重新计算当前时间窗口之前的历史数据。
连续查询可不指定时间窗口(Window)。不指定时间窗口(Window)时,会采用计算间隔(Interval)作为时间窗口(Window)。
使用连续查询
连续查询的管理
Lindorm时序引擎提供SQL能力用于管理数据库中的连续查询。
连续查询的创建
在指定的Database下创建一个连续查询。SQL语法可参见CREATE CONTINUOUS QUERY。
说明连续查询归属于指定的数据库, 当数据库删除时,该数据库下的所有连续查询也将被自动删除。
如果不指定数据库, 则在当前数据库(对应USE DATABASE语句指定的数据库)下创建连续查询。
连续查询的删除
从指定的Database下删除一个已存在的连续查询。SQL语法可参见DROP CONTINUOUS QUERY。
连续查询信息的展示
查询已有的连续查询元数据。SQL语法可参见SHOW CONTINUOUS QUERIES。
连续查询的常见场景与示例
数据降精度与长期存储
对于数据量较大的场景,存储成本会成为用户关心的问题。Lindorm时序引擎支持设置每个数据库的保数据有效期(TTL),您可以结合连续查询,将数据降精度后写入到有效期更长的数据库中。以下示例介绍了如何通过连续查询与数据库TTL设置来实现数据降精度与长期存储。
示例
假设,原始数据采样周期为1秒,数据量较大,只能保存最近一个月的数据。降采样到分钟精度后,数据可以保存一年。
创建数据库db_sensor_month,将原始数据存储在db_sensor_month中,数据有效期为30天。
CREATE DATABASE db_sensor_month WITH (ttl=30);
在数据库db_sensor_month中创建表sensor。
USE db_sensor_month; CREATE TABLE sensor ( device_id VARCHAR TAG, region VARCHAR TAG, time TIMESTAMP, temperature DOUBLE, humidity BIGINT);
创建另一个数据库db_sensor_year,存储降精度后的数据,数据有效期为365天。
CREATE DATABASE db_sensor_year WITH (ttl=365);
创建用于保存计算结果的表db_sensor_year.sensor。
USE db_sensor_year; CREATE TABLE sensor ( device_id VARCHAR TAG, region VARCHAR TAG, time TIMESTAMP, temperature DOUBLE, humidity BIGINT);
创建连续查询,执行降采样查询,并将查询结果写入db_sensor_year.sensor。
CREATE CONTINUOUS QUERY db_sensor_year.my_cq WITH(`interval`='1m') AS INSERT into db_sensor_year.sensor(time, temperature, humidity, device_id,region) SELECT time, avg(temperature) as temperature, avg(humidity) humidity, device_id, region FROM db_sensor_month.sensor sample by 60s;
向原始表db_sensor_month.sensor写入数据。
insert into db_sensor_month.sensor(region,device_id,time,temperature,humidity) values ('hz', 'id123', current_timestamp, 37, 70); insert into db_sensor_month.sensor(region,device_id,time,temperature,humidity) values ('hz', 'id123', current_timestamp, 38, 67);
查询结果表db_sensor_year.sensor中降精度后的数据。
select * from db_sensor_year.sensor;
返回结果如下。
+-----------+--------+---------------------------+-------------+----------+ | device_id | region | time | temperature | humidity | +-----------+--------+---------------------------+-------------+----------+ | id123 | hz | 2023-10-08T19:54:00+08:00 | 37.500000 | 68.5 | +-----------+--------+---------------------------+-------------+----------+
通过预计算提升查询性能
对于某些较长时间范围的降采样查询或者跨时间线的聚合查询,如果直接对原始数据进行查询,耗时可能会很长。此时可以通过连续查询对结果进行预计算,在需要的时候直接查询计算后的结果表,其性能可能会更好,也可以有效提升查询吞吐。