PAYATHON 2026

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 时,应按其独立的数据模型和语法判断。

备注:内容仅供参考。