一则来自阿里云的公告让不少物联网团队心头一紧:2026 年 10 月 23 日后,阿里云 InfluxDB® 版将完全退市,对还在使用这套托管服务的物联网团队来说,真正的挑战不是"找一款能写时序数据的数据库",而是如何在不影响业务的前提下,把积累多年的设备监控数据完整迁出,同时让数据架构配得上至少未来 3~5 年的业务增长。
这篇文章想和大家分享一条已经走通的替代路径——从 InfluxDB 迁移至 KaiwuDB 超详细上手指南。
一、迁移前:先把源端盘清楚
正式动手前,建议完成一份源端盘点清单。清单越细,PoC 越准,返工越少:
-
库 / bucket、保留策略(RP)与数据保留时长;
-
measurement 清单,以及每个 measurement 的 tag key、field key、字段类型、时间精度;
-
写入客户端与采集器:哪些应用直接写、哪些走 Telegraf、认证方式是什么;
-
关键查询资产:InfluxQL 语句、报表、大屏、告警规则、对外接口;
-
数据规模:历史总量、日增量、最大基数(series cardinality)、峰值写入吞吐;
-
可接受切换窗口与观察期长度。
盘点出来之后,建议先用 1–2 个代表性 measurement、一个小时间窗口做完整 PoC:写入、查询改写、性能、存储占用全部跑通,再扩大范围。
二、数据模型怎么对:measurement 就是一张时序表
概念映射
InfluxDB 的 Line Protocol 一行数据形如:
<measurement>,<tag_set> <field_set> <timestamp>
映射到 KaiwuDB 时序引擎:
| InfluxDB | KaiwuDB |
|---|---|
| measurement | 时序表名(不存在则自动创建) |
| tag key / tag value | 标签列(TAGS) |
| field key / field value | 数据列 |
| timestamp | 时间戳列,无模式写入时固定为 k_timestamp |
| measurement + tag set 标识的一个 series(实体) | 由**主标签(PRIMARY TAGS)**区分 |
这里有一个 KaiwuDB 特有的机制需要提前理解:主标签(PRIMARY TAGS)。它用于区分不同的实体(例如每个传感器、每台设备),作用上对应 InfluxDB 中“measurement + tag set 确定一条 series”的那层含义。每张时序表至少需要指定一个主标签,且主标签在建表后不允许修改或删除——所以主标签选谁,是建表阶段就必须定下来的事。主标签有两种确定方式,区别很大:
| 方式 | 主标签是什么 | 适用场景 |
|---|---|---|
| 手工建表时指定(推荐) | 你自己指定的列,如 device_id、host、location | 生产环境,尤其是查询有明确过滤/分组模式 |
| 不指定时自动生成 | KaiwuDB 根据标签列的名字和值,自动添加一个名为 primary_tag 的列(类型 VARCHAR),并生成对应的主标签值 | 快速验证、写入链路跑通 |
也就是说,只有在不指定主标签的情况下,KaiwuDB 才会自动生成 primary_tag。如果先用 CREATE TABLE ... PRIMARY TAGS (device_id) 手工建表,再走 Line Protocol 接口写入,KaiwuDB 会直接使用你定义的表和主标签,不会再凭哈希生成 primary_tag;此时它只做写入和必要的加列、加标签动作。
对查询写法的影响:几乎没有。 同一个 measurement 的所有数据落在同一张时序表里,实体之间由主标签区分——但主标签是数据库内部用于数据分区和实体定位的机制,应用层不需要感知它的存在。原来怎么写,现在还怎么写:
-- InfluxDB 中的查询意图
SELECT MEAN\("usage"\) FROM "cpu" WHERE "host" = 'server01'
-- 迁到 KaiwuDB 后,标签过滤写法完全不变
SELECT avg\(usage\) FROM cpu WHERE host = 'server01';
但主标签选谁,对性能影响很大。 这不是可选项,建议在建表阶段就定下来,原因有三:
-
主标签列自动建索引,数据按主标签分区存储。 时序表创建后,KaiwuDB 会自动为主标签列创建索引,并按主标签对不同设备的数据分区存储,用于快速定位指定设备的数据。所以主标签命中实际的查询条件时,过滤、分组、聚合可以直接走索引定位,避免扫描整张表。
-
普通标签建索引有类型限制。 普通标签不自动建索引,需要手工 CREATE INDEX;而索引的标签数据类型必须是整数类型、浮点类型、CHAR 或 NCHAR——不支持 VARCHAR。设备标识恰恰多为字符串(VARCHAR),一旦它沦为普通标签,就连补建索引这条路也走不通。
-
部分函数与主标签强绑定。 例如 diff() 等窗口函数,PARTITION BY 后跟全部主标签列时性能更优;流计算中使用 time_bucket 函数时,必须与全部主标签列一起使用。主标签设计不合理,这些查询的写法会直接受限。
问题在于:自动生成的 primary_tag 是一串哈希,没有任何业务含义(见 3.2 的示例)。 业务查询不会、也无法用它做过滤条件——没人会写 WHERE primary_tag = 'c15cf362...'。实际查询仍然是 WHERE location = 'Beijing',而 location 此时只是普通标签:
-
主标签上的分区与索引用不上,因为查询条件根本不落在主标签上;
-
想退而求其次给 location 补建索引,又会撞上类型限制——VARCHAR 类型的普通标签不支持建索引。
结果就是:查询能出正确结果,但每次都在扫表。数据量小的时候不明显,量一大就现形。因此:
生产环境建议手工建表,把有业务含义、且最常用于过滤和分组的列(如 device_id、host)指定为 PRIMARY TAGS,再走接口写入。 具体做法见 3.3。两种方式的接口和数据格式完全一致,切换时不需要改一行采集代码。
不指定主标签时:自动建表长什么样
先看不预先建表的情况。写入一行 Line Protocol:
meters,location=Beijing current=17\.01,voltage=220,phase=0\.29
由于 meters 表不存在且未指定主标签,KaiwuDB 会自动建表并生成 primary_tag,等价 SQL 如下:
-- 创建时序表 meters
CREATE TABLE meters (
k_timestamp TIMESTAMPTZ NOT NULL,
current FLOAT8,
voltage FLOAT8,
phase FLOAT8
) TAGS (primary_tag VARCHAR(64) NOT NULL, location VARCHAR\)
PRIMARY TAGS (primary_tag);
-- 写入数据
INSERT INTO meters VALUES (NOW(), 17.01, 220, 0.29,
'c15cf362f37e0acc7ecc2db55ec1cc57fc9579ccba9e72c273abb140f568472d', 'Beijing');
查询结果:
k_timestamp | current | voltage | phase | primary_tag | location
---------------------------+---------+---------+-------+--------------------------------------------------+-----------
2024-10-08 07:16:30.404+00 | 17.01 | 220 | 0.29 | c15cf362f37e0acc7ecc2db55ec1cc57fc9579ccba9e72... | Beijing
注意这里的 primary_tag:它是一串由标签名和标签值计算出的哈希,不是 location 本身,也不具备任何业务含义。而业务查询只会写 WHERE location = 'Beijing'——这串哈希没人会用,主标签的分区与索引机制也就形同虚设。
指定主标签:手工建表后再写入
自动建表适合快速跑通链路。进入生产环境前,建议先手工建表并显式指定主标签——同样承载上面那行 Line Protocol 数据,但把 location 提升为主标签,并声明时间精度与压缩算法:
-- 1. 创建时序库,并设置生命周期(对应 InfluxDB 的保留策略)
CREATE TS DATABASE ts_db RETENTIONS 90d;
USE ts_db;
-- 2. 手工建表:以 location 作为主标签,同时声明精度与压缩
CREATE TABLE meters (
k_timestamp TIMESTAMPTZ(3) NOT NULL, -- 毫秒精度
current FLOAT8 COMPRESS 'lz4',
voltage FLOAT8 COMPRESS 'lz4',
phase FLOAT8 COMPRESS 'lz4'
) TAGS (location VARCHAR(64) NOT NULL)
PRIMARY TAGS (location);
表建好之后,写入侧完全不用改——还是同一个 Line Protocol 接口、同一行数据:
meters,location=Beijing current=17\.01,voltage=220,phase=0\.29
因为 meters 表已存在,KaiwuDB 会直接使用这张表和它的主标签定义,只做写入和必要的加列、加标签动作,不会再生成 primary_tag。
写入后按标签过滤定位,写法与 InfluxDB 时代的习惯一致:
SELECT k\_timestamp, current, voltage, phase
FROM meters
WHERE location = 'Beijing';
这样做换来四点收益:
-
查询更快:主标签落在 location 上,而 WHERE location = 'Beijing' 正是业务最常用的过滤条件——查询条件与主标签对齐,KaiwuDB 自动在主标签列上建的索引和按主标签做的数据分区就能真正发挥作用,直接定位数据而不是扫全表;
-
表结构可控:数据类型、VARCHAR 长度、压缩算法、生命周期在建表时就定死,不再靠自动推断和后续 ALTER TABLE;
-
可读可运维:主标签是业务标识而非哈希,排查问题、定位数据、做人工核对都直接;
-
查询写法不受限:time_bucket、diff() 等与主标签绑定的函数可以按预期使用。
注意主标签有硬约束:最多 4 个,不支持浮点类型和除 VARCHAR 之外的变长类型,默认 64 字节、最大 128 字节,且建表后不允许修改或删除。
选主标签的实操建议:挑业务查询最常用来过滤和分组的那一两个标签,通常就是设备标识(如 device_id、host、location)。判断标准很简单——你的 WHERE 和 GROUP BY 里最常出现哪一列,就把哪一列设为主标签。不要选时间戳、浮点数,也不要选高基数的随机值。因为主标签建表后不可改,这一步想不清楚,后续只能重建表、重导数据。
数据类型映射
Line Protocol 数据类型 → KaiwuDB:
| InfluxDB Line Protocol | KaiwuDB |
|---|---|
| Float | FLOAT8 |
| Integer | INT8 |
| UInteger | INT8 |
| String | VARCHAR |
| Boolean | BOOL |
| Unix timestamp | TIMESTAMPTZ |
InfluxDB 字段类型 → KaiwuDB 时序引擎(KDTS 迁移路径):
| InfluxDB | KaiwuDB 时序引擎 |
|---|---|
| BOOLEAN | BOOL |
| INTEGER | INT4 |
| LONG | INT8 |
| DOUBLE | FLOAT8 |
| FLOAT | FLOAT8 |
| STRING | VARCHAR |
| TIMESTAMP | TIMESTAMP |
形成一个上下系列:
为什么选择我们以及迁移前准备
具体如何迁移
三、写入链路切换:改 URL,不改数据格式
无模式写入接口(切换最快)
POST /restapi/influxdb
-
请求头:Content-Type: text/plain、Accept: application/json
-
认证:Authorization: Basic <token> 或 Basic base64(user:password)(token 为 Login 接口生成的认证令牌)
-
请求体:一行或多行 InfluxDB Line 格式数据
-
响应体:code(全部成功为 0,有失败为 -1)、desc、rows(写入行数)、time(执行时间,秒)
示例:
curl \-\-request POST \\
"http://\<KWDB\_HOST\>:8080/restapi/influxdb" \\
\-\-header "Authorization: Basic cm9vdDprd2RicGFzc3dvcmQ=" \\
\-\-header "Content\-Type: text/plain" \\
\-\-data\-binary 'myMeasurement,tag1=value1,tag2=value2 fieldKey="fieldValue" 1556813561098'
成功响应:
\{ "code": 0, "desc": null, "rows": 1, "time": 0\.002 \}
无模式写入的处理规则(务必记牢):
-
表不存在 → 自动创建;列 / 标签不存在 → 自动 ALTER TABLE 添加;未指定的列 / 标签自动填充 NULL;
-
输入数据宽度大于现有类型宽度 → 自动加宽;VARCHAR 类型自动补齐长度;
-
表名、列名大小写敏感,支持数字和特殊符号开头(内部用双引号包裹);
-
默认创建普通时序表;如需写入稀疏时序表,必须先手工创建稀疏时序表;
-
支持毫秒、微秒、纳秒精度,默认纳秒;未指定 timestamp 时,使用所在主机的系统时间(UTC 时区)作为时间戳。
无模式写入是切换成本最低的路径:不用建表,数据先进来。但不预先建表就意味着主标签、数据类型、VARCHAR 长度全交给自动推断,查询条件对不上主标签。因此建议验证阶段用它快速跑通,生产阶段先按 3.3 手工建表、指定主标签,再走同一个接口写入——接口不变、数据格式不变,但查询性能由你说了算。
Telegraf 接口
如果采集侧用的是 Telegraf,改动更小——只需要在 telegraf.conf 的 [[outputs.http]] 段把 KaiwuDB 的 Telegraf 接口配上:
\[\[outputs\.http\]\]
\#\# KaiwuDB RESTful 接口地址,db 参数指定目标时序库
url = "https://your\-host\-ip:port/restapi/telegraf?db=db1"
timeout = "5s"
method = "POST"
headers = \{ "Authorization" = "Basic cm9vdDprd2RicGFzc3dvcmQ=" \}
\#\# 数据格式必须为 influx
data\_format = "influx"
data_format = "influx" 必须保留,其余按实际环境替换主机、端口、库名与认证信息。
建议的切换步骤
-
在非生产库先发一条测试数据,同时包含数值、字符串、多个 tag 和纳秒时间戳;
-
用 SQL 检查自动创建出来的表结构、标签列、数据列,并读回数据核对;
-
应用侧增加 KaiwuDB 双写,持续对比两边写入错误率与数据延迟;
-
双写稳定后,将主写入流量切至 KaiwuDB,观察期内保留旧写入链路;
-
如出现类型冲突、时间精度错误或写入异常,保留原始批次,按已成功的时间窗口与失败批次重试。
四、历史数据迁移:KDTS 全流程
KDTS 是 KaiwuDB 配套的异构数据迁移工具,支持 MySQL、Oracle、PostgreSQL、MongoDB、InfluxDB、OpenTSDB、TDengine 等源端,目标为 KaiwuDB 的时序引擎或关系引擎。针对 InfluxDB 场景:
| 源端 | 目标引擎 | 结构迁移 | 数据迁移 |
|---|---|---|---|
| InfluxDB 1.x | 时序引擎 | ✅ | ✅ |
| InfluxDB 2.x | 时序引擎 | ✅ | ✅ |
图形化界面操作步骤
-
创建工程:在数据迁移导航窗口右键 → 创建 → 工程;
-
创建迁移任务:在工程目录下右键 → 创建 → 迁移;
-
配置迁移任务:
-
迁移方式:仅结构 / 仅数据 / 结构 + 数据;数据源选择 InfluxDB,目的引擎选择时序引擎;
-
源端信息:选择连接模式(常规 / 离线),填写主机或 URL、端口、认证信息,系统会自动校验连接;
-
目的信息:填写 KaiwuDB 主机或 URL 连接信息,同样自动校验;
-
迁移选项:设置自动执行、迁移约束、迁移视图,以及通道与流量控制参数;
-
选择迁移对象(整库或多表),配置映射关系与迁移策略;
-
-
执行并监控:配置检查无误后执行,实时查看进度与日志;
-
校验:执行一致性校验,查看自动生成的迁移报告。
如果已按 3.3 手工建好目标表并指定了主标签,记得在迁移选项中取消“自动执行”,避免 KDTS 重新执行建表 DDL、把主标签退回自动生成的 primary_tag。
InfluxDB 源端关键参数
| 参数 | 是否必填 | 说明 |
|---|---|---|
| 开始时间(大于等于) | ✅ | 格式 yyyy-MM-dd HH:mm:ss,与结束时间配合实现按区间迁移 |
| 结束时间(小于) | ✅ | 同上 |
| 切分时间间隔 | ✅ | 按自定义时间范围分批读取,避免单次读取数据量过大导致内存不足或响应超时 |
| 读取数据超时时间 | ✗ | 读取超时控制 |
| 建立连接超时时间 | ✗ | 连接超时控制 |
目标端可设置写入模式(INSERT / UPSERT,默认 INSERT)、写入前要执行的语句、写入后要执行的语句。
迁移选项中影响效率的关键参数:
| 参数 | 默认值 | 说明 |
|---|---|---|
| 全局通道数量 | 1 | 控制并行度,建议设为 CPU 核心数的 1~1.5 倍 |
| 全局字节流量限制 | 1048576(1 MB/s) | 控制总带宽 |
| 全局读取记录数限制 | 1000 | 设为 -1 表示无限制 |
| 单通道字节流量限制 | 1048576(1 MB/s) | 控制单通道带宽 |
| 单通道读取记录数限制 | 1000 | 设为 -1 表示无限制 |
命令行(Headless)模式
适合无图形界面的服务器环境或需要集成到自动化脚本的场景。
导出源端元数据:
\./'KaiwuDB Data Transformer' \-headless \-nosplash \-consoleLog \\
\-dsType INFLUXDB1X \-dsHost 127\.0\.0\.1 \-dsPort 8086 \-dsUser root
\-dsType 支持 INFLUXDB1X、INFLUXDB2X、TDENGINE3X、MYSQL、ORACLE、POSTGRESQL;也可用 \-url 替代 \-dsHost / \-dsPort 组合。
执行结构或数据迁移(需先在图形化界面完成配置并导出配置文件):
\./'KaiwuDB Data Transformer' \-headless \-nosplash \-consoleLog \\
\-migrationConfigPath /home/kaiwudb/config/config\.json
分批迁移策略建议
-
先小后大:先选一个 measurement 和一个小时间窗口(如 1 天)跑通,确认表结构、记录数、时间边界、字段类型都正确,再扩大范围;
-
重点核对主标签:KDTS 迁移路径下 measurement 与标签列如何映射为主标签,建议先用小样本实测确认。若发现主标签不符合预期,改为按 3.3 手工建表并取消“自动执行”,把主标签指定为常用的设备标识列;
-
按时间窗口推进:利用“开始时间 + 结束时间 + 切分时间间隔”,以天或周为单位逐个窗口迁移,每个窗口迁移完立即核对记录数与最小 / 最大时间戳;
-
增量靠双写覆盖:历史迁移不能覆盖迁移过程中的新增写入,因此双写必须先于历史迁移启动;
-
失败保留现场:某批次失败时保留该批次配置,修正后重跑该窗口即可,不必整体重来;
-
校验收口:迁移完成后执行一致性校验并查阅迁移报告,确认无异常记录后再进入切读阶段。
备选路径:DataX 插件
如果团队已有 DataX 体系,KaiwuDB 提供 DataX Utils 插件,源端支持 InfluxDB10Reader(InfluxDB 1.x)与 InfluxDB20Reader(InfluxDB 2.x),写入端使用 KaiwuDBWriter。这条路径更适合已有 DataX 作业编排的团队。
五、查询层改造:InfluxQL → KaiwuDB SQL
KaiwuDB 时序引擎使用 标准 SQL + 时序扩展函数。下面给出常见 InfluxQL 意图的改写对照。
| InfluxQL 查询意图 | KaiwuDB SQL |
|---|---|
| 时间范围过滤 | WHERE k_timestamp >= '...' AND k_timestamp < '...' |
| 标签条件 | WHERE tag_name = 'value' |
| MEAN() / MAX() / MIN() / COUNT() | avg() / max() / min() / count() |
| GROUP BY time(1m) | GROUP BY TIME_WINDOW(k_timestamp, '1m') 或 time_bucket(k_timestamp, '1m') |
| GROUP BY tag | GROUP BY tag_name |
| LAST(field) | last(field)(不含 NULL)或 last_row(*)(含 NULL,取整行) |
| fill(previous / linear / null) | interpolate(avg(expr), PREV / LINEAR / NULL),配合 time_bucket_gapfill() |
| 保留策略 RP | RETENTIONS(库级 / 表级) |
性能提示:上表中的 WHERE tag_name = 'value' 和 GROUP BY tag_name,如果 tag_name 正是主标签(按 3.3 的方式手工建表指定),查询条件与主标签对齐,自动建好的索引和按主标签的数据分区就能直接用上,避免扫描整张表。这也是为什么建议在迁移阶段就把主标签设计好——查询写法不用改,但性能差别很大。
时间窗口聚合
统计某表 10 分钟窗口内的记录数与平均值,窗口间不重叠:
SELECT count\(ts\) AS records, avg\(speed\) AS avg\_speed
FROM vehicles
GROUP BY TIME\_WINDOW\(ts, '10m'\);
带滑动步长(窗口 10 分钟、起始间隔 5 分钟,窗口间有重叠):
SELECT count\(ts\) AS records, avg\(speed\) AS avg\_speed
FROM vehicles
GROUP BY TIME\_WINDOW\(ts, '10m', '5m'\);
按设备分组 + 窗口聚合,并输出窗口起止时间:
SELECT first\(k\_timestamp\) AS window\_start,
last\(k\_timestamp\) AS window\_end,
device\_id,
min\(voltage\)
FROM sensors
GROUP BY time\_window\(k\_timestamp, '10min'\)
ORDER BY window\_start DESC;
KaiwuDB 还提供最值上下文查询:在使用 min() / max() 的同时,直接返回最值所在行的其他列,一次查询拿到完整上下文,不必再自关联一次。
使用 time_bucket 函数时,必须与全部主标签列一起使用(见 7.1 流计算部分)。这也是主标签需要在建表阶段就设计好的原因之一——它直接决定了部分聚合查询的写法。
按标签分组统计
SELECT region,
MAX\(usage\) AS max\_usage,
COUNT\(usage\) AS sample\_count
FROM ts\_db\.cpu
WHERE k\_timestamp \>= '2024\-01\-01 00:00:00'
AND k\_timestamp \< '2024\-01\-02 00:00:00'
GROUP BY region;
时间条件建议统一采用左闭右开区间,避免相邻迁移窗口的数据重复或遗漏。
最新值与完整最新行
-- 取某设备最新一条记录的全部字段(含 NULL)
SELECT last\_row\(\*\) FROM ts\_db\.cpu WHERE device\_id = 'device01';
-- 取某列最后一个非空值(不含 NULL)
SELECT last\(usage\) FROM ts\_db\.cpu WHERE device\_id = 'device01';
···
\-\- 取指定截止时间前的最新值
SELECT last\(usage, '2024\-01\-01 00:00:00'\) FROM ts\_db\.cpu WHERE device\_id = 'device01';
字段可能缺失的场景用 last(),需要整行完整快照用 last_row(*);last_row_ts() 则直接返回最新行的时间戳。
最近 N 条原始数据
SELECT k\_timestamp, usage, load
FROM ts\_db\.cpu
WHERE device\_id = 'device01'
ORDER BY k\_timestamp DESC
LIMIT 10;
缺失值填充:两条路径
路径一:窗口聚合场景——time_bucket_gapfill() + interpolate()
先按固定间隔补齐缺失的时间戳行,再对数据列补值。补值模式支持 prev(前值)、next(后值)、linear(线性插值)、null 和常量值:
SELECT time\_bucket\_gapfill\(k\_timestamp, 86400\) AS tt,
interpolate\(avg\(temperature\), PREV\) AS temperature
FROM ts\_db\.sensor
GROUP BY tt
ORDER BY tt;
注意:time_bucket_gapfill() 必须与 GROUP BY 配合使用;如果需要同时查询其他列,且该列不在 GROUP BY 范围内,需要用聚合函数处理(例如 max(c1))。
路径二:精确时间点取值——FILL 子句
针对“查询某个精确时间点的值、该点无数据”的工业测点场景,KaiwuDB 提供 6 种填充策略:
| 填充方式 | 说明 |
|---|---|
| FILL(EXACT) | 精确匹配,无数据返回 NULL |
| FILL(PREVIOUS) | 取之前最近的有效值(可指定向前查找窗口,单位 ms) |
| FILL(NEXT) | 取之后最近的有效值 |
| FILL(CLOSER) | 取前后时间点中距离最近的有效值 |
| FILL(CONSTANT, value) | 用指定常量替换 |
| FILL(LINEAR) | 线性插值(可指定前后查找区间) |
SELECT k\_timestamp, data1, data2
FROM ts\_db\.metric\_ts
WHERE device\_id = 'device1'
AND k\_timestamp = '2025\-12\-19 10:00:02\.200'
FILL\(PREVIOUS\);
数值列(INT2/4/8、FLOAT4/8)支持全部六种;BOOL、字符、字节类型不支持 LINEAR。
保留策略改写
InfluxDB 的保留策略(RP)在 KaiwuDB 中对应生命周期(RETENTIONS),支持库级与表级设置,表级优先于库级:
\-\- 库级:创建时序库并设置生命周期
CREATE TS DATABASE ts\_db RETENTIONS 50d;
ALTER TS DATABASE ts\_db SET RETENTIONS = 10 day;
\-\- 表级
CREATE TABLE temp \(
k\_timestamp TIMESTAMPTZ NOT NULL, temperature FLOAT8
\) TAGS \(sensor\_id INT NOT NULL\) PRIMARY TAGS \(sensor\_id\) RETENTIONS 20D;
SHOW RETENTIONS ON TABLE temp;
单位为 s / m / h / d / w / mon / y,取值范围为正整数,上限 1000 年,默认 0s(永久保留)。超过生命周期的数据会被系统自动清除;待写入数据若已超过生命周期限制,会被直接丢弃。 配合冷热分级存储机制,可按采集时间自动将数据迁移到热、温、冷不同级别的存储目录。
六、迁移之后:把能力往前推一步
完成写入和查询迁移后,有几件事原本需要外挂组件或定时任务完成,现在可以在数据库内直接做。建议在基础迁移和查询回归完成后逐步引入,不要与切库同时上线。
流计算:实时降采样与预计算加速
流计算基于 CDC 机制实时捕获写入的时序数据,用 SQL 定义过滤规则与计算逻辑,将结果写入目标表(时序表或关系表)。典型用途是把高频原始数据(如每秒 1000 点)实时降采样后保存,或对重复查询做预计算加速。
\-\- 按 hostname 分组,1 分钟窗口、30 秒滑动步长,
\-\- 计算 usage\_user / usage\_system 的平均值并写入 cpu\_avg
CREATE STREAM cpu\_stream INTO cpu\_avg AS
SELECT first\(ts\_timestamp\),
last\(ts\_timestamp\),
count\(\*\),
avg\(usage\_user\),
avg\(usage\_system\),
hostname
FROM benchmark\.cpu
GROUP BY hostname, TIME\_WINDOW\(ts\_timestamp, '1m', '30s'\);
关键参数与限制:
-
select_list 中必须包含 first(ts) 和 last(ts) 且作为最开始的两个输出列,用于记录窗口起止时间,否则历史数据、过期数据和断点数据处理可能不可用;
-
MAX_DELAY(窗口最大持续时间,默认 24h)、SYNC_TIME(乱序数据窗口,默认 1m,必须小于 MAX_DELAY)、PROCESS_HISTORY(是否处理历史与断点数据)、MAX_RETRIES(默认 5)、CHECKPOINT_INTERVAL(默认 10s)、LOW_LATENCY 等可按业务调整;
-
支持滑动窗口、会话窗口、状态窗口;
-
不支持对多个时序表 / 时序库 / 关系表做流计算、不支持分布式集群高可用、不支持同步 DDL(需先停流计算再做 DDL)、不支持指定数据去重规则。
数据推送:把变化实时推给 Kafka
支持在时序库、单个时序表、单表指定列或多个时序表上创建数据推送管道,将数据变化与 DDL 操作以 JSON 格式实时推送至 Kafka 主题,并支持基于时间戳、设备等条件的灵活过滤。适合实时大屏、监控告警、下游系统解耦等场景。
发布订阅:云边协同
企业版支持数据发布(CREATE PUBLICATION)与数据订阅(CREATE SUBSCRIPTION),可将边缘侧或本地集群的时序数据同步到云端实例,例如把降采样后的轻量数据上行、原始明细留在本地。
多模融合与 AI 引擎
时序数据与业务关系数据同库存放后,设备指标可以直接与资产、工单、组织结构等业务表 JOIN,不必再做跨库同步与对齐。企业版还提供可插拔的 AI 预测分析引擎,支持通过 SQL 函数导入和部署预训练模型,对时序数据做预测与异常检测。
七、推荐的低风险切换流程
| 阶段 | 操作 | 预期结果 |
|---|---|---|
| 1. 建立目标端、确定边界 | 部署并创建 KaiwuDB 时序库(按需设置 RETENTIONS),按 3.3 手工建表并指定主标签,记录历史迁移截止点 T0、写入与查询验收基线 | 目标端可接收测试数据,表结构与主标签已定型 |
| 2. 保护增量 | 从 T0 起启动应用双写(Line Protocol 接口或 Telegraf 接口) | 新增数据同时进入两端 |
| 3. 迁移历史 | 用 KDTS 迁移 T0 之前的历史数据,按时间窗口分批推进 | 历史数据按窗口逐步到达目标端 |
| 4. 最终追平 | 在切换窗口停止旧写入,完成最后一个增量窗口 | 时间边界与数据量对齐 |
| 5. 校验 | 执行 KDTS 一致性校验,核对记录数、最小 / 最大时间戳、抽样聚合与关键查询,查阅迁移报告 | 关键业务结果一致或差异已确认 |
| 6. 切换读取 | 将读请求改为 KaiwuDB SQL,灰度发布 | 业务稳定运行 |
| 7. 下线旧链路 | 观察期结束且无数据差异后停止旧链路 | 迁移完成 |
最容易犯的错误是“先搬历史、再开双写”。 历史迁移工具只能覆盖迁移时刻已有的数据,无法自动包含迁移过程中的新增写入——顺序反了,就必然产生数据缺口。
八、容易踩的 9 个坑(来自产品限制,建议逐条确认)
-
时间精度:无模式写入支持毫秒 / 微秒 / 纳秒,默认纳秒;而手工建表时时间戳列默认毫秒精度。混合使用两种建表路径时,务必明确指定精度并保持一致。
-
主标签记得自己指定:主标签可以在手工建表时用 PRIMARY TAGS 指定,只有不指定时 KaiwuDB 才会自动生成 primary_tag 列、把主标签值填成一串哈希。哈希没有业务含义,查询时几乎不会用它做过滤条件,主标签上的分区与索引因此白白闲置;而真正用于过滤的设备标识列沦为普通标签,偏偏 VARCHAR 类型的普通标签又不支持建索引。查询能出正确结果,但一直在扫表。加上主标签建表后不允许修改或删除,事后发现只能重建表、重导数据。生产环境请务必手工建表并显示指定 PRIMARY TAGS,挑最常用于过滤分组的设备标识列。
-
主标签长度与类型约束:主标签最多 4 个,默认 64 字节、最大 128 字节,且不支持浮点类型和除 VARCHAR 之外的变长类型。若设备标识较长(例如带完整层级路径的测点名),手工建表时务必预留足够长度,否则写入会失败。
-
稀疏时序表:无模式写入默认创建普通时序表,如需稀疏时序表必须提前手工创建。
-
字符串类型宽度:VARCHAR 会自动补齐长度,但如果首个批次的值很短,可能导致后续写入触发 ALTER TABLE;建议手工建表时预留合理长度。
-
时间戳缺省行为:Line Protocol 未带 timestamp 时,使用所在主机的系统时间(UTC 时区),可能与业务预期时区不一致。
-
保留策略空档:若目标库设置了 RETENTIONS,早于生命周期的历史数据会被直接丢弃而非写入。历史回灌前请确认生命周期设置,或临时放宽后回灌、再调整。
-
流计算约束:不支持多表、不支持分布式高可用、不支持同步 DDL、不支持数据去重,上线前需对照业务场景确认。
-
列数与标签数上限:单个时序表最多 4096 列、最多 128 个标签;时序表名与列名不支持中文字符。
其中第 2 条是最容易被跳过、也最贵的一条——它不在迁移当时暴露,而是在数据量上来之后以“查询变慢”的形式显现,而那时改造需要重建表加重新导数据。
九、总结
迁移到 KaiwuDB 时,建议把历史数据迁移、实时写入接入、查询改造、能力升级当作一个完整流程来实施:
-
写入侧:Line Protocol 原生兼容,无模式写入接口 /restapi/influxdb 与 Telegraf 接口 /restapi/telegraf 直接承接,采集端通常只需改 URL 与认证;
-
建模侧:主标签可以手工指定,也可以交给 KaiwuDB 自动生成。生产环境建议手工建表并用 PRIMARY TAGS 显式指定,挑业务最常用来过滤分组的设备标识列——主标签列自动建索引、数据按主标签分区,查询条件落在主标签上才能真正用上;若交给自动生成,哈希没有业务含义、查询用不到,主标签的索引和分区就闲置了,而 VARCHAR 普通标签又补不了索引;
-
历史数据:KDTS 支持 InfluxDB 1.x / 2.x 到 KaiwuDB 时序引擎的结构、数据与混合迁移,支持全量与增量、按时间分片分批、一致性校验与迁移报告,图形化与命令行双模式;
-
查询侧:InfluxQL 改写为标准 SQL + 时序扩展函数,重点回归窗口、填充与最新值三类语义;
-
节奏上:先保护增量,再回灌历史,分窗口校验,灰度切读,最后下线旧链路。
针对受该版本退市影响的企业用户,KaiwuDB 可提供一对一迁移评估、PoC 验证、专家咨询与专属迁移优惠。点击提交需求,获取专属技术对接。

评论(0)