Apache IoTDB(15):IoTDB查询写回(INTO子句)深度解析——从语法到实战的ETL全链路指南

Apache IoTDB(15):IoTDB查询写回(INTO子句)深度解析——从语法到实战的ETL全链路指南

引言

在工业物联网场景中,时序数据的存储与处理常面临“数据孤岛”困境——生产设备产生的原始数据需经过清洗、聚合、转换等多步处理,才能转化为可分析的业务指标。Apache IoTDB的查询写回(INTO子句)正是破解这一痛点的“数据炼金术”。通过SELECT INTO语句,能将查询结果直接写入新序列,实现“查询-转换-存储”的闭环,相当于在数据库内部构建轻量级ETL管道。

在这里插入图片描述

Apache IoTDB 时序数据库【系列篇章】

No.文章地址(点击进入)
1Apache IoTDB(1):时序数据库介绍与单机版安装部署指南
2Apache IoTDB(2):时序数据库 IoTDB 集群安装部署的技术优势与适用场景分析
3Apache IoTDB(3):时序数据库 IoTDB Docker部署从单机到集群的全场景部署与实践指南
4Apache IoTDB(4):深度解析时序数据库 IoTDB 在Kubernetes 集群中的部署与实践指南
5Apache IoTDB(5):深度解析时序数据库 IoTDB 中 AINode 工具的部署与实践
6Apache IoTDB(6):深入解析数据库管理操作——增删改查与异构数据库实战指南
7Apache IoTDB(7):设备模板管理——工业物联网元数据标准化的破局之道
8Apache IoTDB(8):时间序列管理——从创建到分析的实战指南
9Apache IoTDB(9):数据库操作——数据写入从CLI到集群部署的六种实战
10Apache IoTDB(10):数据库操作——从查询到优化的全链路实践指南
11Apache IoTDB(11):分段聚合深度解析——从原理到实战的完整指南
12Apache IoTDB(12):深度解析时序数据聚合的GROUP BY与HAVING子句
13Apache IoTDB(13):数据处理的双刃剑——FILL空值填充与LIMIT/SLIMIT分页查询实战指南
14Apache IoTDB(14):IoTDB结果集排序与查询对齐模式——ORDER BY与ALIGN BY DEVICE使用

一、语法定义

SELECT INTO 语句用于将查询结果写入一系列指定的时间序列中。

使用场景

实现 IoTDB 内部 ETL:对原始数据进行 ETL 处理后写入新序列。
查询结果存储:将查询结果进行持久化存储,起到类似物化视图的作用。
非对齐序列转对齐序列:对齐序列从0.13版本开始支持,可以通过该功能将非对齐序列的数据写入新的对齐序列中。

二、使用示例

2.1 语法

selectIntoStatement : SELECT resultColumn [, resultColumn]...INTO intoItem [, intoItem]...FROM prefixPath [, prefixPath]...[WHERE whereCondition][GROUPBY groupByTimeClause, groupByLevelClause][FILL {PREVIOUS | LINEAR | constant}][LIMIT rowLimit OFFSET rowOffset][ALIGN BY DEVICE]; intoItem : [ALIGNED] intoDevicePath '(' intoMeasurementName [',' intoMeasurementName]*')';

2.2 INTO 子句

INTO 子句由若干个 intoItem 构成。

每个 intoItem 由一个目标设备路径和一个包含若干目标物理量名的列表组成(与 INSERT 语句中的 INTO 子句写法类似)。

其中每个目标物理量名与目标设备路径组成一个目标序列,一个 intoItem 包含若干目标序列。例如:root.sg_copy.d1(s1, s2) 指定了两条目标序列 root.sg_copy.d1.s1 和 root.sg_copy.d1.s2。

INTO 子句指定的目标序列要能够与查询结果集的列一一对应。

规则:

按时间对齐(默认):全部 intoItem 包含的目标序列数量要与查询结果集的列数(除时间列外)一致,且按照表头从左到右的顺序一一对应。

按设备对齐(使用 ALIGN BY DEVICE):全部 intoItem 中指定的目标设备数和查询的设备数(即 FROM 子句中路径模式匹配的设备数)一致,且按照结果集设备的输出顺序一一对应。
为每个目标设备指定的目标物理量数量要与查询结果集的列数(除时间和设备列外)一致,且按照表头从左到右的顺序一一对应。

2.3 例子

1.按时间对齐

IoTDB>select s1, s2 into root.sg_copy.d1(t1), root.sg_copy.d2(t1, t2), root.sg_copy.d1(t2)from root.sg.d1, root.sg.d2;+--------------+-------------------+--------+| source column| target timeseries| written|+--------------+-------------------+--------+| root.sg.d1.s1| root.sg_copy.d1.t1|8000|+--------------+-------------------+--------+| root.sg.d2.s1| root.sg_copy.d2.t1|10000|+--------------+-------------------+--------+| root.sg.d1.s2| root.sg_copy.d2.t2|12000|+--------------+-------------------+--------+| root.sg.d2.s2| root.sg_copy.d1.t2|10000|+--------------+-------------------+--------+ Total line number =4 It costs 0.725s 

该语句将 root.sg database 下四条序列的查询结果写入到 root.sg_copy database 下指定的四条序列中。

其中的 root.sg_copy.d2(t1, t2) 也可以写做 root.sg_copy.d2(t1), root.sg_copy.d2(t2)。

INTO 子句的写法非常灵活,只要满足组合出的目标序列没有重复,且与查询结果列一一对应即可。

source column 列表示查询结果的列名
target timeseries 表示对应列写入的目标序列
written 表示预期写入的数据量

2.按时间对齐

IoTDB>selectcount(s1 + s2), last_value(s2)into root.agg.count(s1_add_s2), root.agg.last_value(s2)from root.sg.d1 groupby([0,100),10ms);+--------------------------------------+-------------------------+--------+| source column| target timeseries| written|+--------------------------------------+-------------------------+--------+|count(root.sg.d1.s1 + root.sg.d1.s2)| root.agg.count.s1_add_s2|10|+--------------------------------------+-------------------------+--------+| last_value(root.sg.d1.s2)| root.agg.last_value.s2|10|+--------------------------------------+-------------------------+--------+ Total line number =2 It costs 0.375s 

该语句将聚合查询的结果存储到指定序列中

3.按设备对齐

IoTDB>select s1, s2 into root.sg_copy.d1(t1, t2), root.sg_copy.d2(t1, t2)from root.sg.d1, root.sg.d2 align by device;+--------------+--------------+-------------------+--------+| source device| source column| target timeseries| written|+--------------+--------------+-------------------+--------+| root.sg.d1| s1| root.sg_copy.d1.t1|8000|+--------------+--------------+-------------------+--------+| root.sg.d1| s2| root.sg_copy.d1.t2|11000|+--------------+--------------+-------------------+--------+| root.sg.d2| s1| root.sg_copy.d2.t1|12000|+--------------+--------------+-------------------+--------+| root.sg.d2| s2| root.sg_copy.d2.t2|9000|+--------------+--------------+-------------------+--------+ Total line number =4 It costs 0.625s 

该语句同样是将 root.sg database 下四条序列的查询结果写入到 root.sg_copy database 下指定的四条序列中。但在按设备对齐中,intoItem 的数量必须和查询的设备数量一致,每个查询设备对应一个 intoItem。

按设备对齐查询时,CLI 展示的结果集多出一列 source device 列表示查询的设备。

4.按设备对齐

IoTDB>select s1 + s2 into root.expr.add(d1s1_d1s2), root.expr.add(d2s1_d2s2)from root.sg.d1, root.sg.d2 align by device;+--------------+--------------+------------------------+--------+| source device| source column| target timeseries| written|+--------------+--------------+------------------------+--------+| root.sg.d1| s1 + s2| root.expr.add.d1s1_d1s2|10000|+--------------+--------------+------------------------+--------+| root.sg.d2| s1 + s2| root.expr.add.d2s1_d2s2|10000|+--------------+--------------+------------------------+--------+ Total line number =2 It costs 0.532s 

该语句将表达式计算的结果存储到指定序列中

三、变量占位符

特别的可以使用变量占位符描述目标序列与查询序列之间的对应规律,简化语句书写。目前支持两种变量占位符。

  1. 后缀复制符 :::复制查询设备后缀(或物理量),表示从该层开始一直到设备的最后一层(或物理量),目标设备的节点名(或物理量名)与查询的设备对应的节点名(或物理量名)相同。
  2. 单层节点匹配符 i :表示目标序列当前层节点名与查询序列的第 i 层节点名相同。比如,对于路径 r o o t . s g 1. d 1. s 1 而言, {i}:表示目标序列当前层节点名与查询序列的第i层节点名相同。比如,对于路径root.sg1.d1.s1而言, i:表示目标序列当前层节点名与查询序列的第i层节点名相同。比如,对于路径root.sg1.d1.s1而言,{1}表示sg1, 2 表示 d 1 , {2}表示d1, 2表示d1,{3}表示s1。
    在使用变量占位符时,intoItem与查询结果集列的对应关系不能存在歧义

按时间对齐(默认):变量占位符只能描述序列与序列之间的对应关系,如果查询中包含聚合、表达式计算,此时查询结果中的列无法与某个序列对应,因此目标设备和目标物理量都不能使用变量占位符。

(1)目标设备不使用变量占位符 & 目标物理量列表使用变量占位符
限制:

1.每个 intoItem 中,物理量列表的长度必须为 1。
(如果长度可以大于1,例如 root.sg1.d1(::, s1),无法确定具体哪些列与::匹配)
2.intoItem 数量为 1,或与查询结果集列数一致。
(在每个目标物理量列表长度均为 1 的情况下,若 intoItem 只有 1 个,此时表示全部查询序列写入相同设备;若 intoItem 数量与查询序列一致,则表示为每个查询序列指定一个目标设备;若 intoItem 大于 1 小于查询序列数,此时无法与查询序列一一对应)

匹配方法: 每个查询序列指定目标设备,而目标物理量根据变量占位符生成。

例:

select s1, s2 into root.sg_copy.d1(::), root.sg_copy.d2(s1), root.sg_copy.d1(${3}), root.sg_copy.d2(::)from root.sg.d1, root.sg.d2;

等于下面的语句

select s1, s2 into root.sg_copy.d1(s1), root.sg_copy.d2(s1), root.sg_copy.d1(s2), root.sg_copy.d2(s2)from root.sg.d1, root.sg.d2;

(2)目标设备使用变量占位符 & 目标物理量列表不使用变量占位符
限制: 全部 intoItem 中目标物理量的数量与查询结果集列数一致。

匹配方式: 为每个查询序列指定了目标物理量,目标设备根据对应目标物理量所在 intoItem 的目标设备占位符生成。

例:

select d1.s1, d1.s2, d2.s3, d3.s4 into ::(s1_1, s2_2), root.sg.d2_2(s3_3), root.${2}_copy.::(s4)from root.sg;

(3)目标设备使用变量占位符 & 目标物理量列表使用变量占位符
限制: intoItem 只有一个且物理量列表的长度为 1。

匹配方式: 每个查询序列根据变量占位符可以得到一个目标序列。

例:

select*into root.sg_bk.::(::)from root.sg.**;

将 root.sg 下全部序列的查询结果写到 root.sg_bk,设备名后缀和物理量名保持不变

按设备对齐(使用 ALIGN BY DEVICE)
注:变量占位符只能描述序列与序列之间的对应关系,如果查询中包含聚合、表达式计算,此时查询结果中的列无法与某个物理量对应,因此目标物理量不能使用变量占位符。

(1)目标设备不使用变量占位符 & 目标物理量列表使用变量占位符
限制: 每个 intoItem 中,如果物理量列表使用了变量占位符,则列表的长度必须为 1。

匹配方法: 每个查询序列指定目标设备,而目标物理量根据变量占位符生成。

例:

select s1, s2, s3, s4 into root.backup_sg.d1(s1, s2, s3, s4), root.backup_sg.d2(::), root.sg.d3(backup_${4})from root.sg.d1, root.sg.d2, root.sg.d3 align by device;

(2)目标设备使用变量占位符 & 目标物理量列表不使用变量占位符
限制: intoItem 只有一个。(如果出现多个带占位符的 intoItem,我们将无法得知每个 intoItem 需要匹配哪几个源设备)

匹配方式: 每个查询设备根据变量占位符得到一个目标设备,每个设备下结果集各列写入的目标物理量由目标物理量列表指定。

例:

selectavg(s1),sum(s2)+sum(s3),count(s4)into root.agg_${2}.::(avg_s1, sum_s2_add_s3, count_s4)from root.** align by device;

(3)目标设备使用变量占位符 & 目标物理量列表使用变量占位符
限制: intoItem 只有一个且物理量列表的长度为 1。

匹配方式: 每个查询序列根据变量占位符可以得到一个目标序列。

例:

select*into ::(backup_${4})from root.sg.** align by device;

将 root.sg 下每条序列的查询结果写到相同设备下,物理量名前加backup_。

指定目标序列为对齐序列
通过 ALIGNED 关键词可以指定写入的目标设备为对齐写入,每个 intoItem 可以独立设置。

例:

select s1, s2 into root.sg_copy.d1(t1, t2), aligned root.sg_copy.d2(t1, t2)from root.sg.d1, root.sg.d2 align by device;

该语句指定了 root.sg_copy.d1 是非对齐设备,root.sg_copy.d2是对齐设备。

不支持使用的查询子句
SLIMIT、SOFFSET:查询出来的列不确定,功能不清晰,因此不支持
LAST查询、GROUP BY TAGS、DISABLE ALIGN:表结构和写入结构不一致,因此不支持

需注意:

对于一般的聚合查询,时间戳是无意义的,约定使用 0 来存储
当目标序列存在时,需要保证源序列和目标时间序列的数据类型兼容
当目标序列不存在时,系统将自动创建目标序列(包括 database)
当查询的序列不存在或查询的序列不存在数据,则不会自动创建目标序列

四、内部ETL实现

对原始数据进行 ETL 处理后写入新序列。

IOTDB >SELECT preprocess_udf(s1, s2)INTO ::(preprocessed_s1, preprocessed_s2)FROM root.sg.* ALIGN BY DEIVCE;+--------------+-------------------+---------------------------+--------+| source device| source column| target timeseries| written|+--------------+-------------------+---------------------------+--------+| root.sg.d1| preprocess_udf(s1)| root.sg.d1.preprocessed_s1|8000|+--------------+-------------------+---------------------------+--------+| root.sg.d1| preprocess_udf(s2)| root.sg.d1.preprocessed_s2|10000|+--------------+-------------------+---------------------------+--------+| root.sg.d2| preprocess_udf(s1)| root.sg.d2.preprocessed_s1|11000|+--------------+-------------------+---------------------------+--------+| root.sg.d2| preprocess_udf(s2)| root.sg.d2.preprocessed_s2|9000|+--------------+-------------------+---------------------------+--------+

以上语句使用自定义函数对数据进行预处理,将预处理后的结果持久化存储到新序列中。

查询结果存储

将查询结果进行持久化存储,起到类似物化视图的作用

IOTDB >SELECTcount(s1), last_value(s1)INTO root.sg.agg_${2}(count_s1, last_value_s1)FROM root.sg1.d1 GROUPBY([0,10000),10ms);+--------------------------+-----------------------------+--------+| source column| target timeseries| written|+--------------------------+-----------------------------+--------+|count(root.sg.d1.s1)| root.sg.agg_d1.count_s1|1000|+--------------------------+-----------------------------+--------+| last_value(root.sg.d1.s2)| root.sg.agg_d1.last_value_s2|1000|+--------------------------+-----------------------------+--------+ Total line number =2 It costs 0.115s 

以上语句将降采样查询的结果持久化存储到新序列中。

非对齐序列转对齐序列

对齐序列从 0.13 版本开始支持,可以通过该功能将非对齐序列的数据写入新的对齐序列中。

注意: 建议配合使用 LIMIT & OFFSET 子句或 WHERE 子句(时间过滤条件)对数据进行分批,防止单次操作的数据量过大。

IOTDB >SELECT s1, s2 INTO ALIGNED root.sg1.aligned_d(s1, s2)FROM root.sg1.non_aligned_d WHEREtime>=0andtime<10000;+--------------------------+----------------------+--------+| source column| target timeseries| written|+--------------------------+----------------------+--------+| root.sg1.non_aligned_d.s1| root.sg1.aligned_d.s1|10000|+--------------------------+----------------------+--------+| root.sg1.non_aligned_d.s2| root.sg1.aligned_d.s2|10000|+--------------------------+----------------------+--------+ Total line number =2 It costs 0.375s 

以上语句将一组非对齐的序列的数据迁移到一组对齐序列

五、用户权限与配置参数

相关用户权限

用户必须有下列权限才能正常执行查询写回语句:

所有 SELECT 子句中源序列的 WRITE_SCHEMA 权限
所有 INTO 子句中目标序列 WRITE_DATA 权限

相关配置参数

select_into_insert_tablet_plan_row_limit

在这里插入图片描述

总结

Apache IoTDB的INTO子句通过“查询即存储”的创新设计,实现了时序数据处理的性能突破、功能突破、易用性突破:通过类SQL语法降低使用门槛,配合变量占位符实现动态查询在工业物联网、智能电网、车联网等场景中,INTO子句已成为时序数据处理的核心之一。通过本文的深度解析,不仅能掌握INTO子句的语法细节,更能理解其背后的设计哲学——让数据库自身成为数据处理的核心引擎。

Read more

假网站排全网第二,真官网翻五页都找不到!NanoClaw创始人破防:SEO之战,我快要输了

假网站排全网第二,真官网翻五页都找不到!NanoClaw创始人破防:SEO之战,我快要输了

整理 | 苏宓 出品 | ZEEKLOG(ID:ZEEKLOGnews) 自从 OpenClaw 爆火之后,各种“Claw”项目接连出现,其中以安全优化版 NanoClaw 最为知名。它的核心代码仅有 4000 行,却获得了 AI 大牛 Andrej Karpathy 的点赞。 可谁也没想到,这款口碑极佳的开源项目,近来竟被一个仿冒网站抢了风头。 投诉无门之下,NanoClaw 创始人 Gavriel Cohen 在 X 社交平台上无奈发文怒斥:谷歌搜索错误地将假网站排在真官网前面,不仅破坏了项目声誉,还埋下了严重的安全隐患,而他费尽心力,却只能哀叹一句——“我正在为自己的开源项目打 SEO 战,但我快要输了。” 那么,NanoClaw 究竟发生了什么?又是怎么走红的?事情还要从 OpenClaw

By Ne0inhk
曝Windows 12将于今年发布?以AI为核心、NPU成「硬件门槛」,网友吐槽:“不想要的全塞进来了”

曝Windows 12将于今年发布?以AI为核心、NPU成「硬件门槛」,网友吐槽:“不想要的全塞进来了”

整理 | 郑丽媛 出品 | ZEEKLOG(ID:ZEEKLOGnews) 当年,微软一句“Windows 10 将是最后一个版本”的表态,让不少用户以为 Windows 进入了“只更新、不换代”的时代。但几年过去,现实却完全不同。 在 Windows 11 发布之后,如今关于 Windows 12 的传闻再次密集出现。从内部代号、代码片段,到硬件厂商的暗示与 OEM 预热标签,种种线索拼在一起,勾勒出一个明显的趋势——这不会只是一次常规升级,而更像是一次围绕 AI 的平台级重构。 更关键的是,这次争议,可能远比当年 TPM 2.0 更大。 精准卡位 Windows 10 退场的时间?

By Ne0inhk
Python热度下滑、AI能取代搜索引擎?TIOBE最新榜单揭晓!

Python热度下滑、AI能取代搜索引擎?TIOBE最新榜单揭晓!

整理 | 屠敏 出品 | ZEEKLOG(ID:ZEEKLOGnews) 日前,TIOBE 发布了最新的 3 月编程语言榜单。整体来看,本月排名变化不算大,但榜单中仍然出现了一些值得关注的小波动。  AI 工具能帮大家秒懂最新编程语言趋势? 由于 2 月天数较少,3 月的榜单整体变化有限。借着这次发布,TIOBE CEO Paul Jansen 也回应了一个最近被频繁讨论的问题:为什么 TIOBE 指数仍然依赖搜索引擎统计结果?在大语言模型流行的今天,直接询问 AI 哪些编程语言最流行,是不是更简单? 对此,Jansen 的回答是否定的。 他解释称,TIOBE 指数本质上统计的是互联网上关于某种编程语言的网页数量。而大语言模型的训练数据同样来自这些网页内容,因此从信息来源来看,两者并没有本质区别。换句话说,LLM 的判断,本质上也是建立在这些网页数据之上的。 Python 活跃度仍在下降

By Ne0inhk
“裸奔龙虾”数量已达27万只,业内人士警告;AI浪潮下,中传“砍掉”翻译等16个专业;薪资谈判破裂,三星电子8.9万人要罢工 | 极客头条

“裸奔龙虾”数量已达27万只,业内人士警告;AI浪潮下,中传“砍掉”翻译等16个专业;薪资谈判破裂,三星电子8.9万人要罢工 | 极客头条

「极客头条」—— 技术人员的新闻圈! ZEEKLOG 的读者朋友们好,「极客头条」来啦,快来看今天都有哪些值得我们技术人关注的重要新闻吧。(投稿或寻求报道:[email protected]) 整理 | 郑丽媛 出品 | ZEEKLOG(ID:ZEEKLOGnews) 一分钟速览新闻点! * “裸奔龙虾”已高达27万只!业内人士警告:一旦黑客入侵,敏感信息一秒搬空 * 阿里云 CTO 周靖人代管千问模型一号位,刘大一恒管理更多团队 * 中国传媒大学砍掉翻译、摄影等 16 个本科专业,直言教育要面向人机分工时代 * 雷军放话:小米将很快推出 L3、L4 的驾驶 * 消息称原理想汽车智驾一号位郎咸朋具身智能赛道创业 * vivo 前产品经理宋紫薇创业,瞄准 AI 时尚Agent,获亿元融资 * MiniMax 发布龙虾新技能,股价暴涨超 23% * 薪资谈判破裂,三星电子

By Ne0inhk