从 InfluxDB 1.x 迁移到 TDengine:端到端数据迁移与查询改写实战指南
【免费下载链接】TDengineHigh-performance, scalable time-series database designed for Industrial IoT (IIoT) scenarios项目地址: https://gitcode.com/GitHub_Trending/tde/TDengine
迁移不是单次数据导入。为避免历史数据、迁移期间新增数据和业务查询出现缺口,应从源端盘点、目标端建模、增量保护、历史回灌、数据校验到读写切换依次闭环完成。
TDengine 作为面向工业物联网(IIoT)场景设计的高性能时序数据库,其无模式(schemaless)写入原生兼容 InfluxDB Line Protocol,并提供了taosAdapter的 InfluxDB v1 写入端点、TDengine Cloud 数据源以及taosX数据同步任务等多种迁移通道。本文基于 TDengine 迁移指南 及 从 InfluxDB 迁移到 TDengine 的完整实施框架,详细讲解将 InfluxDB 1.x 的历史数据、写入链路和查询应用迁移到 TDengine 的评估、实施与验收全过程,覆盖 TDengine Cloud、TDengine TSDB-OSS 与 TDengine TSDB-Enterprise 三种目标产品形态,并给出可复制的 Line Protocol 数据映射、增量保护策略、InfluxQL 到 TDengine SQL 的改写对照与源码级实现佐证。读者完成后可独立规划并执行一次完整的时序数据库迁移。
迁移流程与目标产品形态
推荐采用"先保护增量、再回灌历史、最终追平后切读"的六步流程:
- 盘点源端:摸清数据模型、写入链路和关键查询,确定迁移边界
T0; - 目标端建模:创建目标数据库,并用代表性数据验证数据模型;
- 保护增量:从
T0开始启用应用双写或持续同步,保护新增数据; - 回灌历史:迁移
T0之前的历史数据; - 校验追平:按时间窗口校验数据,停止旧写入后完成最终追平;
- 切换下线:灰度将读请求改为 TDengine SQL,观察期结束后下线旧链路。
三种目标产品形态的 SQL、数据模型和验收原则相同,区别在于历史数据迁移与实时写入的实现方式:
| 目标产品形态 | 历史数据迁移 | 实时写入 | 适用场景 |
|---|---|---|---|
| TDengine Cloud | 通过 Cloud InfluxDB 数据源和连接代理读取源端;可设置结束时间或持续同步 | 使用 Cloud InfluxDB Line Protocol 端点和 Cloud Token | 希望使用全托管服务,且连接代理能够访问源 InfluxDB |
| TDengine TSDB-OSS | 从源端导出 Line Protocol,再经自建taosAdapter导入 | 使用自建taosAdapter的 InfluxDB v1 写入端点 | 希望使用开源版本,并能够维护目标集群和导出链路 |
| TDengine TSDB-Enterprise | 通过taosX和taosExplorer创建 InfluxDB 数据源任务;可持续同步 | 使用自建taosAdapter的 InfluxDB v1 写入端点 | 需要可视化任务管理、进度恢复或私有化部署 |
本文中的 InfluxDB Line Protocol 映射适用于 TDengine 的无模式写入。关于协议完整语法、类型推断和限制,请参阅 无模式写入;特定数据源的连接器配置、协议语法和组件参数,请参阅 数据接入专题文档。
迁移前评估和目标端准备
盘点源端
在创建迁移任务前,应记录以下信息并保存为迁移验收基线:
| 项目 | 需要确认的内容 |
|---|---|
| 数据范围 | 数据库、保留策略、最早和最新时间戳、历史数据量、每日增量和迁移截止点T0 |
| 数据模型 | measurement、tag、field、字段类型、空值比例和 tag 基数 |
| 时间语义 | 写入精度、时区处理方式、乱序数据范围和迟到数据的最大延迟 |
| 写入链路 | 应用、采集器、批量大小、重试策略、认证方式和是否能够双写 |
| 读取链路 | 关键 InfluxQL 查询、报表、告警、接口以及可接受的切换窗口 |
| 源端能力 | 是否可直接导出 Line Protocol;不能直接导出时,是否需要使用源服务商提供的备份或迁出方式 |
此外,对每个 measurement 选择一个较小时间窗口作为试迁移样本。样本应包含多个 tag、数值和字符串 field、空值以及纳秒时间戳等具有代表性的数据,以便在正式迁移前暴露类型冲突、精度丢失等问题。
创建目标数据库
InfluxDB 的时间精度可以混用秒、毫秒、微秒和纳秒。为避免精度丢失,迁移目标数据库应使用纳秒精度。例如:
CREATE DATABASE migration_db PRECISION 'ns';生产迁移前还应完成以下准备:
- 为迁移程序和应用分别创建最小权限账号或凭据;
- 验证迁移主机、连接代理或
taosX-Agent到源端和目标端的网络连通性; - 确定双写开始时间
T0、历史数据截止时间和最终切换窗口; - 为导出文件、失败批次、校验结果和迁移日志分配独立存储空间;
- 在非生产数据库完成一次完整的试迁移和查询回归。
数据模型和写入语义
通过 InfluxDB Line Protocol 写入时,TDengine 按下表映射数据模型:
| InfluxDB 概念 | TDengine 概念 |
|---|---|
| measurement | 超级表名称 |
| tag key/value | 标签列;tag 值自动转换为NCHAR |
| field key/value | 普通列;按类型后缀或引号推断类型 |
| timestamp | 主键时间戳,默认列名为_ts |
| measurement 和 tag set | 子表;默认按排序后的 tag 计算 MD5 生成表名 |
例如,下面这条 Line Protocol:
cpu,host=server01,region=cn-beijing usage=42.5,load=2i,status="ok" 1704067200000000000会创建或使用超级表cpu,将host、region写为标签列(NCHAR),将usage(f64后缀缺省映射DOUBLE)、load(i后缀映射BIGINT)、status(双引号映射VARCHAR)写为普通列,并将末尾纳秒时间戳写入_ts。
无模式写入的底层映射规则(源码佐证)
上述映射不是魔法,而是 TDengine 无模式写入模块的既定行为。从 无模式写入文档 与 无模式写入客户端实现 可以看到:
- 行协议格式为
measurement,tag_set field_set timestamp,一次调用可传入多行批量写入; - 子表名默认生成规则:将 measurement 名称与按标签名升序排列的
tag_key=tag_value组合为字符串"measurement,tag_key1=tag_value1,tag_key2=tag_value2",计算该字符串的 MD5 散列值后拼装为t_md5_val,t_为固定前缀。因此自动生成的子表名不可读; - 若不想用自动生成的表名,可通过
taos.cfg配置smlAutoChildTableNameDelimiter(指定分隔符拼接,如配置为-后st,t0=cpu1,t1=4 c1=3 ...会创建表名cpu1-4)或smlChildTableName(指定某个 tag 的值作为表名)来定制。这两个配置项及smlTsDefaultName(自定义时间列名,不配置时默认为_ts)均在 tglobal.c 中以CFG_SCOPE_CLIENT注册,属于客户端生效的动态配置; - 数值类型通过后缀区分:无后缀或
f64为double(8 字节)、f32为float、i8/u8为TinyInt/UTinyInt、i16/u16为SmallInt/USmallInt、i32/u32为Int/UInt、i64/i/u64/u为BigInt/UBigInt;t/T/true/f/F/false直接作为BOOL处理;带双引号为VARCHAR,L"..."前缀为NCHAR,G"..."前缀为GEOMETRY,B"..."前缀为VARBINARY; - 超级表、子表名称区分大小写;表名中的点号(
.)会自动替换为下划线(_)。
迁移前应重点确认的语义
- 类型冲突会导致写入失败:同一 field 在不同数据行中出现冲突类型(如一行声明
DOUBLE、另一行声明BIGINT)会触发解析错误,应先统一源端类型或拆分字段; - 空值语义:未出现的 field 或 tag 会以
NULL写入;无模式写入可增加列(只增不减),但不会自动删除既有列; - 自动表名不可读:若业务依赖可读表名,应在试迁移中验证子表命名配置(
smlChildTableName/smlAutoChildTableNameDelimiter); - 长度限制:单行最大长度为 64 KB(源码常量
TSDB_MAX_BYTES_PER_ROW),全部 tag 值总长度最大为 16 KB,超限数据需在源端拆分或转换; - 不要预建同名超级表:不要在首次无模式写入前手工创建同名但结构不同的超级表,否则插入数据可能异常;
- 批量非原子:无模式写入提供幂等性保证(可反复调用 API 重试出错数据),但不提供多行批量写入的原子性,一批数据中可能出现部分成功、部分失败,需按失败批次重试。
保护增量数据
历史导出或备份只能覆盖其开始前已经存在的数据,不能自动包含迁移期间的新增写入。因此,开始历史回灌前必须保护增量数据,否则"先导历史、再对增量"的衔接会出现缺口。
可采用以下方式之一:
- 应用双写:从
T0开始,应用同时写入源 InfluxDB 和 TDengine。应用应保留失败重试或持久化队列,以便补发未确认的数据; - 持续同步:TDengine Cloud 或 TDengine TSDB-Enterprise 的 InfluxDB 数据源任务不设置结束时间时,可持续读取新增数据。仍应监控任务延迟和错误,并在切换窗口完成最终校验;
- 采集器双输出:支持多个输出目标的采集器可同时向源端和 TDengine 写入。必须分别监控两个输出的失败率。
无论使用哪种方式,均应记录T0。历史迁移只处理T0前的数据,增量链路处理T0及之后的数据,从而使两个范围可独立校验。
迁移历史数据
所有路径均应遵循同一原则:先迁移单个 measurement 的小时间窗口,确认模型、记录数和时间边界后,再扩大范围。下文分别说明三种目标形态的实施方式。
TDengine Cloud:InfluxDB 数据源 + 连接代理
TDengine Cloud 可以在数据写入页面创建 InfluxDB 数据源,并通过连接代理访问源 InfluxDB。连接代理必须部署在能够访问源端的网络中。创建任务时:
- 在 Cloud 实例中创建纳秒精度的目标数据库;
- 配置连接代理和源端 InfluxDB 1.x 的只读账号;
- 执行连通性检查,确认代理可以获取源端数据;
- 选择需要迁移的 measurement,设置起始时间;设置结束时间时执行历史迁移,不设置结束时间时持续同步;
- 根据源端负载和数据密度设置单次读取的时间范围。范围过大可能增加源端内存压力,范围过小会降低迁移效率;
- 设置延迟以覆盖可能的乱序或迟到数据,并观察任务延迟和错误。
TDengine TSDB-Enterprise:taosExplorer + taosX
TDengine TSDB-Enterprise 通过taosExplorer创建 InfluxDB 数据源任务,由taosX从源端读取数据并写入目标数据库。界面操作细节可参考 InfluxDB 数据源(taosExplorer)。创建任务时:
- 选择纳秒精度的目标数据库;
- 配置源 InfluxDB 1.x 的地址、用户和密码,并执行连通性检查;
- 选择 measurement、起始时间和可选的结束时间;
- 根据源端性能设置每次读取的时间范围和延迟;
- 提交任务后观察进度、延迟和错误;暂停、重启或异常恢复后,任务会从已保存的进度继续执行(进度信息持久化在硬盘上,不会从头开始)。
任务创建界面中几个关键字段的语义(见 09-influxdb.md):
- 认证:支持
1.x 版本(用户 + 密码)与2.x 版本(组织 ID + Token)两种鉴权模式,二者 API 差异较大,需按源端实际版本选择;InfluxDB 2.x 的"组织 ID"是十六进制字符串而非组织名称;"添加数据库保留策略(DBRP)"开关用于在 InfluxDB Cloud 及部分 2.x 版本中自动补齐 InfluxQL 查询所需的 DBRP 映射; - 桶 Bucket:每个任务指定一个 Bucket,需先点击"获取 Schema"获取源端数据结构再选择;
- 测量值 Measurements:非必填,可多选,不指定则同步全部;
- 起始时间:必填,时区使用 explorer 所选时区;
- 结束时间:可选,不指定时持续同步最新数据;
- 每次读取的时间范围(分钟):单次读取的最大时间范围,过小则同步慢,过大可能因内存使用过高导致源端故障;
- 延迟(秒):范围 1~30 的整数,为消除乱序数据影响,TDengine 总是等待指定时长后才读取数据。
TDengine TSDB-OSS:导出 Line Protocol + taosAdapter 导入
taosAdapter负责接收写入请求,不会主动读取源 InfluxDB。因此,社区版需要先从源端导出 InfluxDB Line Protocol,再分批写入 TDengine。
导出方式取决于源端形态:
- 源端具有本地 InfluxDB 数据目录时,可使用与源版本匹配的导出工具生成 Line Protocol。导出命令和选项随 InfluxDB 版本而变化,应先在一个小时间范围内验证导出结果;
- 源端是托管服务且不提供本地数据目录时,应使用服务商提供的迁出方法(例如云厂商的 TSDB for InfluxDB 迁出方案通常要求先按其文档备份并恢复到自建 InfluxDB 中继,再使用
influx_inspect export -lponly导出 Line Protocol)。此类服务商专有前提、端口和资源要求可能变化,应以服务商最新文档为准。
导入时遵循以下原则:
- 以 measurement 和时间窗口拆分导出文件,文件名中保留时间范围;
- 先导入小批次,并使用 SQL 验证表结构、时间精度和字段类型;
- 对成功批次记录 measurement、时间范围、行数和校验结果;
- 对失败批次保留原始文件,修复数据后仅重试失败批次;
- 历史回灌期间持续运行增量保护链路。
无模式写入的导入参数和限制请参阅 taosAdapter 参考手册 与 无模式写入。
切换实时写入
历史数据追平后,需要将应用的实时写入链路从 InfluxDB 切换到 TDengine。三种形态下写入端点格式不同。
TDengine Cloud:InfluxDB Line Protocol 写入端点
TDengine Cloud 的 InfluxDB Line Protocol 写入端点格式如下:
POST <TDENGINE_CLOUD_URL>/influxdb/v1/write?db=<TDENGINE_DATABASE>&token=<TDENGINE_CLOUD_TOKEN>&precision=ns将 Cloud Token 通过密钥管理服务、环境变量或运行时注入提供,不要写入源码、脚本仓库或日志。以下示例使用环境变量写入一条纳秒精度数据:
curl --request POST \ "$TDENGINE_CLOUD_URL/influxdb/v1/write?db=$TDENGINE_DATABASE&token=$TDENGINE_CLOUD_TOKEN&precision=ns" \ --data-binary 'cpu,host=server01,region=cn-beijing usage=42.5,load=2i,status="ok" 1704067200000000000'TDengine TSDB-OSS 和 TDengine TSDB-Enterprise:taosAdapter 写入端点
自建taosAdapter的 InfluxDB v1 写入端点格式如下:
POST http://<TAOS_ADAPTER_HOST>:6041/influxdb/v1/write?db=<TDENGINE_DATABASE>&precision=ns该接口(实现说明见 taosAdapter 参考手册 的 InfluxDB v1 数据写入小节)支持:
- HTTP Basic Auth和 URL 参数
u、p两种认证方式;目前不支持 InfluxDB 的 token 验证方式; - TDengine TSDB-Enterprise 还支持使用
Authorization: Bearer <token>传入由CREATE TOKEN生成的 TDengine Bearer Token(注意:该 Token 不是 InfluxDB Token); - 可通过 URL 参数
precision指定时间精度(此处为ns);db指定目标数据库名;还支持ttl(自动创建子表的生命周期)与table_name_key(自定义子表名使用的标签名)参数。
以下示例向目标数据库写入一条纳秒精度数据:
curl --request POST \ "http://<TAOS_ADAPTER_HOST>:6041/influxdb/v1/write?db=<TDENGINE_DATABASE>&precision=ns" \ --user "<TDENGINE_USER>:<TDENGINE_PASSWORD>" \ --data-binary 'cpu,host=server01,region=cn-beijing usage=42.5,load=2i,status="ok" 1704067200000000000'从taosAdapter侧看,InfluxDB 协议写入默认启用(配置项influxdb.enable默认true),写入请求与 RESTful、OpenTSDB 等接口共享连接池;无模式写入的smlAutoCreateDB参数默认为false,即目标数据库需提前手动创建,否则写入失败。
切换写入时的操作要点:先在非生产数据库验证上述数据能够创建正确的超级表、标签列和普通列;然后启用双写,持续观察写入失败率、端到端延迟和字段类型冲突;双写稳定后逐步增加 TDengine 的主写入流量,并在观察期内保留旧写入链路。
校验、切换和回滚
在历史迁移、持续同步或双写完成后,按 measurement 和时间窗口执行校验。不要只比对全库总行数,因为总量相同不能证明时间范围和关键字段一致。
| 校验项 | 建议方法 |
|---|---|
| 时间边界 | 比对源端和目标端每个窗口的最小、最大时间戳 |
| 数据量 | 比对每个 measurement、tag 范围或业务维度的记录数 |
| 字段内容 | 抽样比对指定时间戳的字段值、tag 值和空值 |
| 聚合结果 | 比对COUNT、MIN、MAX、AVG等代表性聚合 |
| 写入质量 | 比对双写期间的失败率、重试次数和端到端延迟 |
| 查询行为 | 回归关键报表、告警和 API,确认窗口、填充和最新值语义 |
建议使用左闭右开的时间范围划分校验窗口,例如[_start, _end),避免相邻窗口重复或遗漏数据。
切换窗口内按以下顺序操作:
- 暂停旧写入,或冻结新写入进入旧库;
- 等待双写队列或持续同步任务处理完最后一个增量窗口;
- 对最后一个窗口执行数据校验;
- 灰度将读请求切换为 TDengine SQL;
- 观察关键指标、告警和业务结果;
- 观察期结束且无未解决差异后,下线旧读写链路。
回滚预案:出现字段类型冲突、时间精度错误、数据延迟超出阈值或关键查询结果不一致时,应停止扩大切换范围,将应用读写切回旧链路。根据应用持久化队列、写入日志或失败批次补发未确认数据,重新校验后再开始下一轮切换。
改造 InfluxQL 查询
迁移后,应用读请求需要从 InfluxQL 改写为 TDengine SQL。以下是常见对应关系:
| InfluxQL 查询意图 | TDengine SQL 方向 |
|---|---|
| 时间范围过滤 | WHERE _ts >= ... AND _ts < ... |
| tag 条件 | WHERE tag_name = 'value' |
MEAN、MAX、COUNT | AVG、MAX、COUNT |
GROUP BY time(1m) | INTERVAL(1m) |
| 按 tag 分组 | PARTITION BY tag_name或GROUP BY tag_name,按查询语义选择 |
LAST(field) | LAST(field)或LAST_ROW(*) |
fill(null/previous/linear) | FILL(NULL/PREV/LINEAR) |
下面给出五类高频查询的具体改写示例(时间条件统一使用左闭右开区间,避免相邻迁移和校验窗口之间产生重复或遗漏)。
时间范围、标签筛选和窗口聚合
下面的 InfluxQL 查询按主机统计一分钟窗口内的平均 CPU 使用率:
SELECT MEAN("usage") FROM "cpu" WHERE time >= '2024-01-01T00:00:00Z' AND time < '2024-01-01T00:02:00Z' AND "host" = 'server01' GROUP BY time(1m), "host"可改写为:
SELECT _wstart AS window_start, host, AVG(usage) AS avg_usage FROM migration_db.cpu WHERE _ts >= '2024-01-01 00:00:00.000000000' AND _ts < '2024-01-01 00:02:00.000000000' AND host = 'server01' PARTITION BY host INTERVAL(1m);按标签分别聚合
下面的 InfluxQL 查询按region统计指定时间范围内的 CPU 最大值和样本数:
SELECT MAX("usage"), COUNT("usage") FROM "cpu" WHERE time >= '2024-01-01T00:00:00Z' AND time < '2024-01-02T00:00:00Z' GROUP BY "region"使用PARTITION BY可以让每个region独立计算:
SELECT region, MAX(usage) AS max_usage, COUNT(usage) AS sample_count FROM migration_db.cpu WHERE _ts >= '2024-01-01 00:00:00.000000000' AND _ts < '2024-01-02 00:00:00.000000000' PARTITION BY region;当需要逐个子表计算时,使用PARTITION BY tbname。例如,以下查询返回每个子表在一小时内的平均值:
SELECT tbname, _wstart AS window_start, AVG(usage) AS avg_usage FROM migration_db.cpu WHERE _ts >= '2024-01-01 00:00:00.000000000' AND _ts < '2024-01-01 01:00:00.000000000' PARTITION BY tbname INTERVAL(1h);最新值和完整最新行
若需要返回同一条最新记录中的全部字段,可使用LAST_ROW(*):
SELECT LAST_ROW(*) FROM migration_db.cpu WHERE host = 'server01';若只需要字段的最后一个非空值,可使用LAST(expr)或LAST(*)。窗口查询中的FILL选项、LAST与LAST_ROW的完整语义请参阅 数据查询 和 函数。
最近 N 条原始数据
下面的 InfluxQL 查询获取server01最近的 10 条 CPU 数据:
SELECT "usage", "load" FROM "cpu" WHERE "host" = 'server01' ORDER BY time DESC LIMIT 10可改写为:
SELECT _ts, usage, load FROM migration_db.cpu WHERE host = 'server01' ORDER BY _ts DESC LIMIT 10;注意:在 TDengine SQL 中,LIMIT在ORDER BY之后生效;使用PARTITION BY时,LIMIT会限制每个分区的输出数量。
窗口缺失值填充
当报表需要连续的时间窗口时,可以通过FILL指定缺失窗口的填充方式。下面的 InfluxQL 查询使用前一个有效值填充缺失窗口:
SELECT MEAN("usage") FROM "cpu" WHERE time >= '2024-01-01T00:00:00Z' AND time < '2024-01-01T01:00:00Z' AND "host" = 'server01' GROUP BY time(1m) fill(previous)可改写为:
SELECT _wstart AS window_start, AVG(usage) AS avg_usage FROM migration_db.cpu WHERE _ts >= '2024-01-01 00:00:00.000000000' AND _ts < '2024-01-01 01:00:00.000000000' AND host = 'server01' INTERVAL(1m) FILL(PREV);在上线前,应按实际业务分别验证FILL(NULL)、FILL(PREV)和FILL(LINEAR)的结果。它们会改变缺失窗口的展示和下游计算语义,不能仅根据语法名称推断等价性。
迁移后的能力扩展
完成基础数据校验和查询回归后,可以逐步引入 TDengine 的流式计算、数据订阅和虚拟表;不建议与基础切换同时上线。这些能力应分别建立功能测试、性能基线和回滚措施,再逐步投入生产使用。
流式计算
流式计算 可持续生成分钟级或小时级聚合表,也可将阈值和事件计算结果提供给告警服务。下面的示例按一分钟窗口计算 CPU 平均使用率,并将结果写入cpu_usage_1m:
CREATE STREAM cpu_usage_1m_stream INTERVAL(1m) SLIDING(1m) FROM migration_db.cpu INTO cpu_usage_1m AS SELECT _twstart AS ts, AVG(usage) AS avg_usage FROM %%trows;数据订阅
数据订阅 可将新写入数据或查询结果以主题形式分发给下游消费者,减少定时轮询。下面的查询主题将 CPU 数据提供给告警或实时分析服务:
CREATE TOPIC cpu_realtime_topic AS SELECT tbname, _ts, usage, status FROM migration_db.cpu;注意:查询主题不支持聚合和时间窗口。需要订阅聚合结果时,应先通过流式计算将结果写入表,再订阅该结果表。
虚拟表
虚拟表 可按时间戳组合多个物理表的列,适合为应用提供统一的只读查询入口。下面的示例将同一设备的 CPU 和环境指标组合为一张虚拟表:
CREATE VTABLE device_overview ( ts TIMESTAMP, cpu_usage DOUBLE FROM migration_db.cpu_server01.usage, temperature FLOAT FROM migration_db.env_server01.temperature );虚拟表不直接存储数据。查询时,来源表中相同时间戳的列会组合为同一行;仅一个来源存在的时间戳会保留,缺失列为NULL。示例中的来源表必须替换为迁移后实际存在的物理表或子表。
总结
一次成功的 InfluxDB 到 TDengine 迁移,本质上是"数据链路"与"查询语义"的双重迁移:前者依靠 Line Protocol 的天然兼容性(measurement → 超级表、tag → 标签列、field → 普通列、时间戳 →_ts)和三条历史数据通道(Cloud 数据源、taosX任务、导出导入),配合T0增量保护与逐窗口校验实现无缝衔接;后者则需要把 InfluxQL 的窗口聚合、标签分组、最新值与填充语义逐一改写为等价的 TDengine SQL。迁移完成后,流式计算、数据订阅与虚拟表等 TDengine 原生能力可作为下一阶段的增量收益,逐步释放平台价值。
【免费下载链接】TDengineHigh-performance, scalable time-series database designed for Industrial IoT (IIoT) scenarios项目地址: https://gitcode.com/GitHub_Trending/tde/TDengine
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考