Apache IoTDB 能否用一条 INSERT 向多个设备写入数据?
Apache IoTDB 2.0.6 的 tree model 中,一条 INSERT ... VALUES 语句只能指定一个设备路径,不能同时向多个不同设备写入数据。该语句可以写入同一设备下的多个 measurement,也可以写入多行数据。两个设备的时间戳相同与否,都不影响这一限制。依据:v2.0.6 SQL 语法定义
如果想减少逐条写入的调用开销,可以使用原生批量接口 insertRecords,通过一次 API 调用提交多个设备的数据。
为什么两种 SQL 都会报错?
v2.0.6 的 tree model 使用以下解析规则:
insertStatement
: INSERT INTO prefixPath insertColumnsSpec ALIGNED? VALUES insertValuesSpec
;
规则中只有一个 prefixPath,后面的列清单属于该设备。
- 第一种写法在第一个设备的列清单之后添加了逗号和第二个设备。解析器此时只接受可选的
ALIGNED或VALUES,因此报告expecting {ALIGNED, VALUES}。 - 第二种写法在
INSERT INTO后直接放了括号,没有提供设备路径,因此报告expecting ROOT。列清单中的完整路径不能替代必需的设备路径;timestamp是时间列标识符。
这两个错误都发生在语法解析阶段,修改数值或调整时间戳无法解决。
只使用 SQL 时,按设备分别插入
针对问题中的两条记录,可以执行:
INSERT INTO root.sg.d1(timestamp, temperature)
VALUES (1000, 25.0);
INSERT INTO root.sg.d2(timestamp, humidity)
VALUES (1500, 55.0);
同一设备的数据可以合并成多行:
INSERT INTO root.sg.d1(timestamp, temperature, humidity)
VALUES (1000, 25.0, 45.0), (2000, 26.0, 46.0);
这两种写法都符合 tree model 的写入方式。将多条 SQL 放在同一个脚本中执行,仍然是多条语句。参考:官方写入文档
需要跨设备批量写入时,使用 insertRecords
Java Native API 的 insertRecords 接收设备、时间戳、measurement、数据类型和值这五组列表。相同下标的元素对应一条记录,可以为不同设备设置相同或不同的时间戳。参考:Java Native API
下面的示例假设已经建立 Session 连接,且目标序列为非对齐时间序列,temperature 和 humidity 的数据类型均为 DOUBLE:
import java.util.Arrays;
import java.util.Collections;
import org.apache.iotdb.rpc.IoTDBConnectionException;
import org.apache.iotdb.rpc.StatementExecutionException;
import org.apache.iotdb.session.Session;
import org.apache.tsfile.enums.TSDataType;
public class MultiDeviceWriter {
public static void write(Session session)
throws IoTDBConnectionException, StatementExecutionException {
session.insertRecords(
Arrays.asList("root.sg.d1", "root.sg.d2"),
Arrays.asList(1000L, 1500L),
Arrays.asList(
Collections.singletonList("temperature"),
Collections.singletonList("humidity")
),
Arrays.asList(
Collections.singletonList(TSDataType.DOUBLE),
Collections.singletonList(TSDataType.DOUBLE)
),
Arrays.asList(
Collections.<Object>singletonList(25.0d),
Collections.<Object>singletonList(55.0d)
)
);
}
}
示例提交了两条记录:root.sg.d1 在 1000 时刻的 temperature=25.0,以及 root.sg.d2 在 1500 时刻的 humidity=55.0。如需使用相同的时间戳,将时间列表改为 Arrays.asList(1000L, 1000L) 即可。
使用时注意什么?
- 五个外层列表的长度必须一致;每条记录内部的 measurement、类型和值也必须一一对应。
DOUBLE是示例前提。如果已有序列是FLOAT或其他类型,应相应调整TSDataType和 Java 值类型。- 对齐时间序列使用对应的
insertAlignedRecords。如果每个设备都有较多行数据,可以考虑按设备构建Tablet,再使用insertTablets;这些接口可在官方 API 列表中查到。 - 一次批量 API 调用不等于跨设备事务,也不应据此承诺端到端只有一次网络往返。应用仍需处理写入异常,并根据部署环境评估实际吞吐和延迟。
上述 SQL 限制针对问题中的 Apache IoTDB 2.0.6 tree model;使用 table model 时,应按其独立的数据模型和语法判断。
备注:内容仅供参考。
