1. TDengine时序数据库基础操作入门时序数据库是处理时间序列数据的专业工具而TDengine作为国产开源时序数据库其操作方式与传统关系型数据库既有相似又有独特之处。我们先从最基础的单条数据写入开始。假设你正在开发一个智能电表监控系统需要记录电表的实时数据。首先创建一个名为power的数据库和对应的超级表metersCREATE DATABASE power; USE power; CREATE STABLE meters ( ts TIMESTAMP, current FLOAT, voltage INT, phase FLOAT ) TAGS ( location BINARY(50), group_id INT );超级表相当于一个模板实际数据存储在子表中。为设备d1001创建子表并插入第一条数据CREATE TABLE d1001 USING meters TAGS (北京朝阳区, 1); INSERT INTO d1001 VALUES (2023-08-01 10:00:00, 10.3, 220, 0.31);这里有几个关键点需要注意时间戳列必须放在第一列数值类型要根据实际场景选择电流用FLOAT电压用INT标签列用于存储设备的元数据2. 高效批量写入实战技巧实际项目中单条写入效率太低TDengine提供了多种批量写入方案。假设每10秒采集一次数据每30秒批量上报3条记录INSERT INTO d1001 VALUES (2023-08-01 10:00:00, 10.2, 220, 0.23), (2023-08-01 10:00:10, 12.6, 218, 0.33), (2023-08-01 10:00:20, 12.3, 221, 0.31);更强大的跨设备批量写入可以同时向多个设备写入数据INSERT INTO d1001 USING meters TAGS (北京朝阳区, 1) VALUES (2023-08-01 10:00:00, 10.2, 220, 0.23), (2023-08-01 10:00:10, 12.6, 218, 0.33) d1002 USING meters TAGS (北京海淀区, 1) VALUES (2023-08-01 10:00:05, 11.5, 219, 0.25);批量写入时要注意单条SQL建议不超过16MB批量写入性能是单条写入的10倍以上可以使用预处理语句进一步优化3. 自动建表与动态写入策略在设备动态接入的场景下自动建表功能特别实用。当写入不存在的子表时自动创建INSERT INTO d1005 USING meters (location) TAGS (上海浦东新区) VALUES (2023-08-01 10:00:00, 10.15, 217, 0.33);这个语句会在d1005不存在时自动创建未指定的标签(group_id)会设为NULL。我在实际项目中用这个特性实现了设备即插即用新设备首次上报数据时自动注册。自动建表也支持批量操作INSERT INTO d1001 USING meters TAGS (北京朝阳区, 1) VALUES (2023-08-01 10:00:00, 10.2, 220, 0.23) d1002 USING meters TAGS (北京海淀区, 2) VALUES (2023-08-01 10:00:05, 11.5, 219, 0.25);4. 数据更新与删除的注意事项TDengine的数据更新与传统数据库不同是通过写入相同时间戳的新数据实现的-- 原始数据 INSERT INTO d1001 VALUES (2023-08-01 10:00:00, 10.2, 220, 0.23); -- 更新电流值 INSERT INTO d1001 VALUES (2023-08-01 10:00:00, 15.7, 220, 0.23);数据删除需要谨慎操作因为删除后无法恢复。按时间范围删除-- 删除2023年7月之前的所有数据 DELETE FROM meters WHERE ts 2023-07-01 00:00:00;特别注意删除操作需要超级表权限建议先SELECT确认要删除的数据大量删除可能影响查询性能5. 基础查询与条件过滤TDengine支持标准SQL查询语法。查询电压超过230V的记录SELECT * FROM meters WHERE voltage 230 ORDER BY ts DESC LIMIT 5;时间范围查询要注意时区问题SELECT * FROM d1001 WHERE ts 2023-08-01 08:00:00 AND ts 2023-08-01 09:00:00;对于标签查询需要使用超级表SELECT * FROM meters WHERE location 北京朝阳区 AND ts NOW() - 1h;6. 强大的聚合查询功能按设备分组计算平均电压SELECT TBNAME AS device_id, AVG(voltage) AS avg_voltage, MAX(current) AS max_current FROM meters WHERE ts 2023-08-01 AND ts 2023-08-02 GROUP BY TBNAME;多维度聚合分析SELECT GROUP_ID AS area, COUNT(*) AS samples, AVG(voltage) AS avg_voltage, STDDEV(current) AS current_stdev FROM meters GROUP BY GROUP_ID;TDengine提供丰富的聚合函数常规函数COUNT, SUM, AVG统计函数STDDEV, SPREAD时序特有DERIVATIVE, IRATE近似计算APERCENTILE7. 时间窗口分析实战按1分钟窗口分析用电量SELECT _WSTART AS window_start, _WEND AS window_end, SUM(current * voltage * phase) AS power FROM meters PARTITION BY TBNAME INTERVAL(1m) SLIDING(30s);这种滑动窗口查询特别适合实时监控场景。我在一个能源项目中用这个功能实现了用电负荷预测。状态窗口可以识别异常状态持续时间SELECT _WSTART, _WEND, _WDURATION/1000 AS duration_sec FROM meters STATE_WINDOW(CASE WHEN voltage 210 THEN 1 ELSE 0 END) WHERE TBNAME d1001;8. 高级查询技巧与应用8.1 数据切分查询按地区切分后计算统计指标SELECT location, AVG(voltage) AS avg_voltage, PERCENTILE(current, 90) AS p90_current FROM meters PARTITION BY location;8.2 嵌套查询优化先筛选异常设备再分析SELECT * FROM ( SELECT TBNAME, MAX(voltage) AS max_v FROM meters GROUP BY TBNAME HAVING MAX(voltage) 250 ) t1 JOIN meters t2 ON t1.TBNAME t2.TBNAME;8.3 最新数据查询获取每个设备最新状态SELECT * FROM meters WHERE ts IN ( SELECT LAST(ts) FROM meters GROUP BY TBNAME );9. 性能优化建议索引策略对常用过滤条件创建标签索引CREATE INDEX idx_location ON meters(location);分区设计根据数据量调整vgroups数量CREATE DATABASE power VGROUPS 10;缓存配置优化内存使用ALTER DATABASE power CACHEMODEL last_row;查询优化避免全表扫描合理使用时间范围硬件配置SSD硬盘能显著提升IO性能10. 常见问题解决方案问题1写入速度突然变慢检查wal_level设置增加bufferPool配置考虑批量写入替代单条写入问题2查询超时添加时间范围限制减少返回数据量检查是否有全表扫描问题3磁盘空间不足调整keep参数自动清理旧数据考虑冷热数据分离存储问题4子表数量过多合并同类设备到同一子表使用标签进行区分在实际项目中我遇到一个典型场景某工厂部署了5000个传感器初期为每个传感器创建独立子表导致元数据膨胀。后来改用按传感器类型分组用标签区分具体设备子表数量减少到20个查询性能提升5倍以上。