連續查詢是一種簡化的流計算能力,能夠定期執行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 | +-----------+--------+---------------------------+-------------+----------+
通過預計算提升查詢性能
對于某些較長時間范圍的降采樣查詢或者跨時間線的聚合查詢,如果直接對原始數據進行查詢,耗時可能會很長。此時可以通過連續查詢對結果進行預計算,在需要的時候直接查詢計算后的結果表,其性能可能會更好,也可以有效提升查詢吞吐。