时序数据库数据写入最佳实践:高效写入策略与技巧详解

Jing Wang

2026-04-17 /

数据写入是时序数据库最基础也是最关键的操作之一。高效的写入策略不仅能提升系统吞吐量,还能降低资源消耗。本文将以TDengine时序数据库为例,详细介绍数据写入的各种方式和最佳实践。

一、基础写入方式

1.1 单条数据写入

最基础的写入方式是向表中插入单条记录。假设设备ID为d1001的智能电表在2018年10月3日14:38:05采集到数据:电流10.3A,电压219V,相位0.31。

INSERT INTO d1001 (ts, current, voltage, phase) 
VALUES ("2018-10-03 14:38:05", 10.3, 219, 0.31);

当INSERT语句中的VALUES部分包含了表的所有列时,可以省略VALUES前的字段列表:

INSERT INTO d1001 VALUES("2018-10-03 14:38:05", 10.3, 219, 0.31);

对于表的时间戳列(第一列),也可以直接使用数据库精度的时间戳:

INSERT INTO d1001 VALUES (1538548685000, 10.3, 219, 0.31);

以上三种SQL的效果完全相同。

1.2 批量数据写入

当需要写入多条数据时,可以在一条INSERT语句中写入多条记录,显著提升写入效率:

INSERT INTO d1001 VALUES
    ("2018-10-03 14:38:05", 10.2, 220, 0.23),
    ("2018-10-03 14:38:15", 12.6, 218, 0.33),
    ("2018-10-03 14:38:25", 12.3, 221, 0.31);

上面的SQL一共写入了三条数据,相比执行三条单独的INSERT语句,批量写入能大幅减少网络交互开销。

1.3 多表写入

对于多个设备的数据,TDengine支持一次向多个表写入数据:

INSERT INTO d1001 VALUES 
    ("2018-10-03 14:38:05", 10.2, 220, 0.23),
    ("2018-10-03 14:38:15", 12.6, 218, 0.33),
    ("2018-10-03 14:38:25", 12.3, 221, 0.31) 
d1002 VALUES 
    ("2018-10-03 14:38:04", 10.2, 220, 0.23),
    ("2018-10-03 14:38:14", 10.3, 218, 0.25),
    ("2018-10-03 14:38:24", 10.1, 220, 0.22)
d1003 VALUES
    ("2018-10-03 14:38:06", 11.5, 221, 0.35),
    ("2018-10-03 14:38:16", 10.4, 220, 0.36),
    ("2018-10-03 14:38:26", 10.3, 220, 0.33);

这条SQL一共写入了九条数据,涉及三张不同的表。

二、高级写入技巧

2.1 指定列写入

可以通过指定列向表的部分列写入数据。SQL中没有出现的列,数据库将自动填充为空值(NULL)。注意,时间戳列必须存在,且值不能为空。

INSERT INTO d1004 (ts, voltage, phase) 
VALUES("2018-10-04 14:38:06", 223, 0.29);

这条数据只包含电压和相位,电流值为NULL。

2.2 写入时自动建表

TDengine支持使用带有USING关键字的自动建表语句进行写入。当子表不存在时,先触发自动建表,再写入数据;当子表已经存在时,则直接写入。

INSERT INTO d1005
USING meters (location)
TAGS ("beijing.chaoyang")
VALUES ("2018-10-04 14:38:07", 10.15, 217, 0.33);

当子表d1005不存在时,先自动建表,标签group_id的值为NULL,再写入数据。

自动建表的INSERT语句也支持在一条语句中向多张表写入数据:

INSERT INTO d1001 USING meters TAGS ("California.SanFrancisco", 2) VALUES 
    ("2018-10-03 14:38:05", 10.2, 220, 0.23),
    ("2018-10-03 14:38:15", 12.6, 218, 0.33),
    ("2018-10-03 14:38:25", 12.3, 221, 0.31) 
d1002 USING meters TAGS ("California.SanFrancisco", 3) VALUES 
    ("2018-10-03 14:38:04", 10.2, 220, 0.23),
    ("2018-10-03 14:38:14", 10.3, 218, 0.25),
    ("2018-10-03 14:38:24", 10.1, 220, 0.22);

2.3 通过超级表写入

TDengine还支持直接向超级表写入数据。需要注意的是,超级表是一个模板,本身不存储数据,写入的数据是存储在对应的子表中。

INSERT INTO meters (tbname, ts, current, voltage, phase, location, group_id)
VALUES("d1001", "2018-10-03 14:38:05", 10.2, 220, 0.23, "California.SanFrancisco", 2);

通过指定tbname列向子表d1001写入一条数据。

三、数据更新与删除

3.1 数据更新

时序数据库支持通过写入重复时间戳的数据来更新记录,新写入的数据会替换旧值:

INSERT INTO d1001 (ts, current) VALUES ("2018-10-03 14:38:05", 22);

当子表d1001中已经存在日期时间为2018-10-03 14:38:05的数据时,current(电流)的新值22会替换旧值。

3.2 数据删除

为方便用户清理由于设备故障等原因产生的异常数据,TDengine支持根据时间戳删除时序数据:

DELETE FROM meters WHERE ts < '2021-10-01 10:40:00.100';

这条SQL将超级表meters中所有时间戳早于2021-10-01 10:40:00.100的数据删除。

注意:数据删除后不可恢复,请慎重使用。建议先使用SELECT语句加WHERE后的删除条件查看要删除的数据内容,确认无误后再执行DELETE。

四、零代码写入方案

为了方便用户轻松写入数据,TDengine已与众多知名第三方工具实现无缝集成,包括:

工具类型代表工具
监控采集Telegraf、collectd、StatsD
消息队列EMQX、HiveMQ、Kafka
监控系统Prometheus

用户只须对这些工具进行简单的配置,便可轻松将数据导入TDengine。

此外,TDengine企业版还提供了丰富的连接器:

  • MQTT
  • OPC
  • AVEVA PI System
  • Wonderware
  • MySQL
  • Oracle

通过在TDengine端配置相应的连接信息,用户无须编写任何代码,即可高效地将来自不同数据源的数据写入数据库。

五、写入性能优化建议

5.1 批量写入优先

  • 尽量使用批量写入而非单条写入
  • 单条SQL写入的数据量建议在1000-5000条之间
  • 减少网络交互次数,提升吞吐量

5.2 合理利用自动建表

  • 使用自动建表机制简化应用逻辑
  • 避免频繁的表存在性检查
  • 减少DDL操作的开销

5.3 时间戳处理

  • 优先使用数值型时间戳,减少解析开销
  • 保持时间戳的时区一致性
  • 避免时间戳乱序写入

5.4 表设计优化

  • 合理设计采集量列,避免过多列
  • 标签值不宜过长
  • 根据数据特征选择合适的库配置

六、压缩率查看

通过查询系统表INS_DISK_USAGE,可以查看数据库的压缩率和磁盘空间:

SELECT * FROM INFORMATION_SCHEMA.INS_DISK_USAGE 
WHERE db_name = 'db_name';

通过如下命令,可以查看表的压缩率及具体分布情况:

SHOW TABLE DISTRIBUTED table_name;

总结

高效的数据写入是时序数据库发挥价值的基础。TDengine时序数据库提供了丰富的写入方式,从单条写入到批量写入,从手动建表到自动建表,从SQL写入到零代码集成,满足不同场景的需求。通过合理选择写入策略,开发者可以充分发挥时序数据库的性能优势,为物联网和工业数据管理平台提供可靠的数据底座。TDengine凭借其高效的写入能力和灵活的接入方式,成为构建实时数据库应用的理想选择。