一、influxdb

1、安装与下载

【centos7安装influxdb教程】
1、安装rpm包 rpm -ivh influxdb-1.8.3.x86_64.rpm 
2、启动服务 systemctl start influxdb
3、查看服务状态  systemctl status influxdb
4、设置自启动 systemctl enable influxdb
5、设置日志级别,防止爆炸 vi  /etc/influxdb/influxdb.conf
[logging]
  level = "error"  # 将默认的"info"改为"error"
限制查询资源(防止过度消耗)
[coordinator]
# max-concurrent-queries = 100  # 限制并发查询数
# query-timeout = "30s"  # 设置查询超时
然后重启服务  systemctl restart influxdb
6、设置密码
# 连接到InfluxDB
influx
# 使用管理员用户登录(如果启用了认证)
auth
# 输入用户名和密码
# 修改用户密码
SET PASSWORD FOR root = 'Ahjuxin_2026'
# 创建新用户并设置密码
CREATE USER <username> WITH PASSWORD '<password>' WITH ALL PRIVILEGES
# 示例
CREATE USER monitor WITH PASSWORD 'MonitorPass456!' WITH ALL PRIVILEGES
7、创建数据库
-- 进入InfluxDB命令行
influx
-- 创建数据库 示例:创建名为telegraf的数据库
CREATE DATABASE telegraf
-- 显示所有数据库
SHOW DATABASES
-- 使用特定数据库
USE data
8、设置数据库保留策略1年
CREATE RETENTION POLICY "1year" ON "data" DURATION 365d REPLICATION 1 DEFAULT
9、查看是否生效
SHOW RETENTION POLICIES ON data

2、导入\导出数据库的命令

Influxdb 导入导出数据库的命令
docker exec -it ebd2a5e0f233 /bin/bash

cd /var/lib/influxdb/

influx_inspect export -datadir "/var/lib/influxdb/data" -waldir "/var/lib/influxdb/wal" -out "export" -database tianjin -retention autogen

influx -import -path=export -precision=ns

注意:指定要导出的数据库名称入tianjin
导出的文件名称为export

docker cp ebd2a5e0f233:/var/lib/influxdb/wal /home

数据的导入
influx -import -path=export -precision=ns

3、influxdb时间

node-red通过influxdb节点存数据到Influxdb数据库中

时间主要根据influxdb数据库服务器时间来定的

# 1. 将时区改为越南
sudo timedatectl set-timezone Asia/Ho_Chi_Minh

# 2. 手动设置当前准确时间(越南时间 2026-06-01 12:37:00)
sudo date -s "2026-06-01 12:37:00"

# 3. 将系统时间写入硬件时钟,防止重启丢失
sudo hwclock --systohc

# 4. 验证
date -R

安装并启用时间同步(CentOS/RHEL)

yum install -y chrony
systemctl enable chronyd
systemctl start chronyd
chronyc sources

Ubuntu/Debian

apt install -y chrony
systemctl enable chronyd
systemctl start chronyd

6、数据库备份导入导出

一、恢复前提​​
​​必须文件​​:
完整备份的 meta 目录(存储数据库结构)
data 目录(含 .tsm 数据文件)或 .bak 备份文件
wal 目录(可选,含未压缩的写入日志)

# 停止 InfluxDB 服务
sudo systemctl stop influxdb
# 备份当前数据(防止覆盖)
sudo cp -r /var/lib/influxdb /var/lib/influxdb_backup

# 解压备份文件(假设备份为 influxdb_backup.tar.gz)
sudo tar -xzvf influxdb_backup.tar.gz -C /var/lib/

# 设置权限
sudo chown -R influxdb:influxdb /var/lib/influxdb

# 重启服务
sudo systemctl start influxdb

4、cpu爆满解决方案

症状:

    influxdb运行几分钟后,内存达到3.3G,内存占比占95%,cpu也达到90%以上

线索: 

 2.1、快速定位

在你的InfluxDB服务器上执行以下两个命令,告诉我结果,我就能立刻判断出主攻方向:

1、看线程:执行 top -H -p $(pgrep influxdb)

   截图或描述:看看是有很多个CPU核心都在工作,还是只有1-2个核心的CPU使用率特别高(接近100%),其他核心很空闲?

  • 判断依据:如果只有2个核心忙,说明是写入IO线程不够
  •                   这是InfluxDB默认配置的通病,高并发写入时的典型表现-4-7

2.2、解决方案

  1. 根本原因:高序列基数

    • 现象SHOW SERIES CARDINALITY 返回的数字非常高。

    • 原因:你的数据结构设计有问题。可能是将日志信息、唯一ID、用户手机号等高可变性的信息作为了标签,导致序列数量爆炸式增长,占满内存

    • 解决方案:这是需要优先排查和解决的问题。

      • 识别“罪魁祸首”:运行Flux查询,统计每个标签的唯一值数量,找出那个值比其他标签高几个数量级的标签。

      • 优化数据结构:将高基数的标签改为字段(field)。字段不会被索引,因此不会消耗那么多内存。如果必须作为标签,需要重新审视业务场景,看是否能通过合并或聚合来降低基数。

      • 清理旧数据:如果某些高基数数据不再需要,可以考虑直接删除整个存储桶(bucket)或特定时间范围的数据。

  2. 根本原因:IO线程不足(写入瓶颈)

    • 现象:运行 top -H 后发现只有2个CPU核心满载,其他核心空闲。

    • 原因:InfluxDB处理网络写入请求的IO线程数默认只有2个。在写入并发较高时,这2个线程会成为瓶颈,不仅CPU利用率上不去,内存也可能因为请求堆积而升高。

    • 解决方案:调整启动配置,增加IO线程数。例如,如果你的服务器有16核,可以尝试设置为:


2.3、其他原因

若以上两个命令输出结果都是正常的话,那要考虑是否改动了什么导致的?

我的原因是废弃的服务器里面的采集服务(之前关闭的),开启了,导致采集数据量加倍


二、tdengine实践文档

一、安装与卸载

1、使用 TDengine 官方安装包卸载
默认安装的位置是/usr/local/taos下
进入bin目录下,执行 ./remove.sh命令
等待出现
TDengine taosd is running, stopping it...
TDengine is removed successfully!

二、命令行登录

登录tdengine库 带密码
taos -uroot -pAh_juxin_2022

查询目前多少台设备在线
select count(*) from tljx.power where ts>now-5m group by head_code;
这里的power是超极表

三、创建超级表和存库

create database db;   #创建数据库

#  修改数据库副本数  集群中副本数必须<=DNODE数目

alter database db replica 2; 


use db;     #进入数据库

#  创建超级表
create stable if not exists Super_Tmp(ts TIMESTAMP,company_name NCHAR(40),num_id INT) TAGS(Temp FLOAT,hum FLOAT)


#   以超级表为模板创建表
create table if not exists tmp USING super_tmp TAGS(2,5)


#   修改超级表的标签
alter stable super_tmp change tag hum hump;
格式:alter stable 超级表名称 change tag 旧名 新名
修改超级表的标签以及列会导致以超级表为模板的子表们都改变;


#   给超级表新增新的一列
alter Stable SUPER_TMP add column note NCHAR(20);


#   查询超级表5分钟有哪些活跃的子表
查询目前多少台设备在线
select count(*) from tljx.power where ts>now-5m group by head_code;
这里的power是超极表

1、创建历史和报警数据超级表

--历史数据超级表

CREATE STABLE tjdk.udf(`ts` timestamp,val float,standval float,maxval float,minval float,states int,outMaxVal float,outMinVal float) TAGS (`head_code` nchar(20),`acq_point` nchar(20));

--报警数据超级表

CREATE STABLE tjdk.alaudf(`ts` timestamp,val float,standval float,maxval float,minval float,states int,outMaxVal float,outMinVal float) TAGS (`head_code` nchar(20),`acq_point` nchar(20));

2、自动创建表存库

msg.sql = "insert into ";
const dbname = "tjdk";//数据库名称
Object.entries(msg.rtdata).forEach(function ([key, v]) {
    let tname = dbname + "." + msg.head_code + "_" + key;
    msg.sql += tname + " using " + dbname + ".udf tags("
        + "'" + msg.head_code + "','" + key + "') "
        + " values(now,";
    msg.sql += v[0] + ",";
    msg.sql += v[1] + ",";
    msg.sql += v[2] + ",";
    msg.sql += v[3] + ",";
    msg.sql += v[4] + ",";
    msg.sql += v[5] + ",";
    msg.sql += v[6] + ")";
});
msg.payload = msg.sql + ";";
return msg;

四、查询语句集合

1、分组条件查询

SELECT last(*) from gw_test.udf where ts> now-10m and head_code in ('thDev','noiceDev','airDev','preDev') 
GROUP by head_code,acq_point;

2、嵌套查询

SELECT
    -- 核心:计算 峰时运转率,保留2位小数
    CONVERT(decimal(10,2),
        AVG(
            CONVERT(decimal(10,2),
                ISNULL(LEFT(PerPeak+'0000',4),0)  -- 安全截取前4位
            )/100  -- 转成百分比
        )
    ) AS 峰时运转率,
    CalDate AS time  -- 日期字段别名 time
FROM [JD_IDS_Operation_DrawingMachine]  -- 设备运行数据表

WHERE
    -- 只查最近 1 个月的数据
    CONVERT(DateTime,CalDate) >= DATEADD(m,-1,GETDATE())
    AND ComCode = '1110'  -- 只查公司编码 1110

GROUP BY CalDate  -- 按天分组
ORDER BY CalDate ASC  -- 按时间从早到晚排序

3、联合查询

需求: 一次获取超级表下面几个子表联合数据

SELECT  a.val as v1,b.val as v2 from tldk.jy01_temp a,tldk.jy01_rev b where a.ts = b.ts  and  a.ts >=now -3m;

返回数据格式

{ "res": true, "count": 18, "data": [ { "v1": 418.6, "v2": 10.974856 }, { "v1": 417.8, "v2": 10.993713 }, { "v1": 416.6, "v2": 10.996858 }, { "v1": 416.4, "v2": 11.006286 }, { "v1": 416.2, "v2": 11.003141 }, { "v1": 415.8, "v2": 10.993713 }, { "v1": 414.8, "v2": 11.018857 }, { "v1": 414.7, "v2": 10.981142 }, { "v1": 415.4, "v2": 10.984286 }, { "v1": 414.6, "v2": 11.006286 }, { "v1": 414.4, "v2": 11.025143 }, { "v1": 413.6, "v2": 11.028285 }, { "v1": 413.1, "v2": 11.025143 }, { "v1": 417.1, "v2": 11.037714 }, { "v1": 421, "v2": 11.050285 }, { "v1": 421.2, "v2": 11.07857 }, { "v1": 419, "v2": 11.069143 }, { "v1": 417.1, "v2": 11.040856 } ] }

4、GROUP BY 查询的 LIMIT/OFFSET 作用于分组内部而非全局结果集

**错误原因**  
在tdengine中,`GROUP BY` 查询的 `LIMIT` 和 `OFFSET` 作用于**每个分组内部**(这里是每个 60 秒时间窗口),而非全局结果集。因此当存在多个时间窗口时,返回数据量为 `窗口数 × LIMIT`,而非预期的全局总行数。

**正确做法**  
使用子查询将聚合结果先计算出来,再在外层应用全局 `LIMIT`/`OFFSET`。

SELECT * FROM (
    SELECT 
        last(val)      AS val,
        last(iwtemp)   AS iwtemp,
        last(diff)     AS diff,
        last(diffmax)  AS diffmax,
        last(diffmin)  AS diffmin,
        last(states)   AS states,
        ts
    FROM tldk.alatemp
    WHERE ts >= '2026-01-05 00:00:00' AND ts < '2026-01-06 20:00:00'
    GROUP BY acq_point, time(60s)
    ORDER BY ts DESC
) 
LIMIT 2 OFFSET 4

5、设备OEE计算

计算机头当天的【有效开机时间】和【运转率】
① 查数据库:统计有效数据条数
从数据表中统计 当天、线速度 > 200 的记录数量
sql
SELECT count(*) FROM table WHERE ts > 当天 AND val > 200
→ 得到 有效采集点数(acq_num)
② 查采集频率
查最后一条数据的时间间隔,知道 多久采一次数据
sql
SELECT diff(ts) / 1000 FROM tljx.${msg.head_code}_ssxr ORDER BY ts DESC LIMIT 1;
③ 计算机头 OEE 运转指标
有效运转率(rate)
有效开机时间(effTime)
无效时间(ineffTime)
2. 最终算出 4 个结果
acq_num
当天线速度 >200 的有效数据条数
rate
有效运转率(0~1,保留两位小数)
effTime
当天有效开机时间(单位:分钟)
一天最多 1440 分钟
ineffTime
当天无效停机时间(1440 - 有效时间)
3. 计算公式(超级简化版)
plaintext
有效运转率 = 有效数据条数 / 当天理论应采集总条数
有效开机时间 = 运转率 × 1440 分钟
无效时间 = 1440 - 有效时间

6、批量插入数据时,时间戳重复导致只存最后一条

   时间戳是数据库的主键,必须唯一。批量插入时如果全部用 NOW,所有数据时间戳都一样,数据库会自动覆盖,最后只留下一条记录。

// 在 Node-RED 的 Function 节点中使用
function saveDeviceStatusToTD(data) {
  let insertSql = "INSERT INTO tldk.device_status_detail (ts, headCode, head_type, param_type) VALUES ";
  let valuesArr = [];
  const baseTs = Date.now() -  8 * 60 * 60 * 1000;
  let offset = 0;

  for (const key in data) {
    const param_type = key.includes("normalDev") ? 1 : 2;
    const head_type = key.includes("udf") ? 1 : 2;

    for (let headCode of data[key]) {
      headCode = headCode.length == 1 ? headCode + "炉" : headCode;
      headCode = headCode.toUpperCase();
      // 使用基准时间 + 偏移量,确保每条记录时间戳不同
      valuesArr.push(`(${baseTs + offset}, '${headCode}', ${head_type}, ${param_type})`);
      offset++;
    }
  }

  insertSql += valuesArr.join(", ");
  return insertSql;
}

7、DISTINCT对单个或多个数据列进行去重

SELECT DISTINCT headCode FROM tldk.device_status_detail WHERE ts > NOW - 1d AND head_type = 1 AND param_type = 1;

8、查询某个时间范围内连续数采的区间

SELECT
  tbname,
  _wstart,
  _wend,
  _wduration,
  count(*)
FROM tljx.z079_vsxzl
WHERE ts >=now -1d
PARTITION BY tbname
SESSION(ts, 1m) 
ORDER BY tbname, _wstart;

9、查询超级表中某个tag长度大于>15的子表

SELECT table_name 
FROM information_schema.ins_tables 
WHERE db_name = 'tljd_datan' 
  AND stable_name = 'datan' 
  AND LENGTH(table_name) > 18;


五、mqtt数据订阅

# TDengine MQTT订阅数据 通俗易懂教程
## 一、前提条件
- TDengine版本要求:≥3.3.7.0
- 参考文档:https://docs.taosdata.com/advanced/subscription/mqtt/

## 二、核心操作步骤(分3大环节)
### 环节1:创建TDengine数据表(超级表+子表)
#### 1.1 创建超级表(模板表)
作用:定义数据结构和标签规则,后续子表基于它创建
```sql
-- 创建juxin库下的udf超级表
CREATE STABLE juxin.udf(
  `ts` timestamp,    -- 时间戳(必选,TDengine核心字段)
  val float,         -- 数值(浮点型)
  standval float,    -- 标准值(浮点型)
  maxval float,      -- 最大值(浮点型)
  minval float,      -- 最小值(浮点型)
  states int         -- 状态值(整型)
) TAGS (`head_code` nchar(20),`acq_point` nchar(20));  -- 标签:设备头编码、采集点(字符型,最长20位)
```

#### 1.2 创建子表(实际存储数据的表)
作用:基于超级表模板,指定具体标签,用于存储对应设备/采集点的数据
```sql
-- 创建juxin库下的fd_temp子表,继承udf超级表结构,标签为"fd"(头编码)、"temp"(采集点)
create table if not exists juxin.fd_temp using juxin.udf tags("fd","temp");
```

### 环节2:开启TDengine数据订阅(创建BNode+订阅主题)
#### 2.1 创建BNode节点(MQTT订阅依赖的节点)
##### 步骤1:查询Dnode ID(先确定节点ID)
```sql
SHOW DNODES;  -- 执行后查看返回结果中的ID(示例中是1)
```
##### 步骤2:创建BNode节点(基于查到的Dnode ID)
```sql
CREATE BNODE ON DNODE 1;  -- 这里的1替换成上一步查到的实际Dnode ID
```
##### 步骤3:验证BNode是否创建成功
```sql
SHOW BNODES;  -- 执行后能看到创建的BNode节点信息即为成功
```

#### 2.2 创建订阅主题(指定要订阅的数据)
作用:定义需要通过MQTT推送的数据范围(示例只订阅最近10分钟的数据)
```sql
-- 创建名为test的订阅主题,订阅juxin.fd_temp子表中最近10分钟的所有数据
create topic test as select * from juxin.fd_temp where ts > now-10m ;
```

### 环节3:Node-RED客户端订阅数据
#### 3.1 核心配置信息
- MQTT节点连接地址:`192.168.1.156`
- MQTT端口:`6083`
- 订阅主题:`test`

#### 3.2 操作简化说明
1. 在Node-RED中拖拽MQTT订阅节点;
2. 配置该节点的连接参数:IP填`192.168.1.156`,端口填`6083`;
3. 订阅主题填写`test`;
4. 部署后即可接收TDengine推送的juxin.fd_temp表最近10分钟的数据。

## 三、关键备注
1. 所有SQL操作需在TDengine客户端(如taos-cli)执行;
2. 创建BNode时的Dnode ID必须用`SHOW DNODES`查到的实际值,不能直接用示例的1;
3. 订阅主题的`where ts > now-10m`是筛选最近10分钟数据,可根据需求调整时间范围(如1h、1d);
4. Node-RED需确保网络能访问192.168.1.156的6083端口。

六、流计算处理(未完)

你可以创建一个流(Stream),持续监听juxin.udf的数据,并在检测到峰值时,将结果写入另一张表中。
1. 创建流计算结果表
首先,为检测到的峰值创建一个结果存储表。这里可以继续使用超级表结构,方便按设备查询历史峰值
-- 创建一个存储峰值记录的超级表
CREATE STABLE IF NOT EXISTS juxin.peak_records (
    ts TIMESTAMP,
    val FLOAT,
    prev_val FLOAT,
    next_val FLOAT
) TAGS (head_code NCHAR(20), acq_point NCHAR(20));

2. 创建流计算任务


CREATE TABLE juxin.downData(
  `ts` timestamp,    -- 时间戳(必选,TDengine核心字段)
   rate float,
   val float         -- 数值(浮点型)
) ;  -- 标签:设备头编码、采集点(字符型,最长20位)

CREATE STREAM juxin.sm1 PERIOD(1h) 
  INTO juxin.fd_down 
  AS
    SELECT last(*),1,max(val) FROM juxin.fd_temp;



SELECT 
  ts,
  change_rate,
  MAX(original_val) as max_val_in_period
FROM (
  SELECT 
    ts,
    val as original_val,
    DERIVATIVE(val, 8s, 0) as change_rate
  FROM juxin.fd_temp 
  WHERE ts > now - 1m 
) AS temp_table
WHERE change_rate > 15
ORDER BY ts DESC;

SELECT * FROM (
  SELECT 
    ts, 
    DERIVATIVE(val, 8s, 0) as change_rate
  FROM juxin.fd_temp 
  WHERE ts > now - 1m 
  ORDER BY ts DESC
) AS temp_table
WHERE change_rate > 15;

七、数据库数据迁移

1、数据库迁移

把windows上的tdengine数据迁移到linux系统的tdengine库

1.1、taosdump
taosdump -H 127.0.0.1 -u root -p taosdata -D tjdk -S "2026-02-01 00:00:00"  -E "2026-03-08 23:59:59" -o C:\juxin\td_backup
1.2、程序读取旧库+存新库
[
    {
        "id": "bd6adaa5521b32c0",
        "type": "taos-query",
        "z": "f6f2187d.f17ca8",
        "server": "bb86570570d747eb",
        "database": "tjdk",
        "sql": "",
        "x": 540,
        "y": 340,
        "wires": [
            [
                "adce2ab7a8392fbf"
            ]
        ]
    },
    {
        "id": "63b02d7acafba141",
        "type": "function",
        "z": "f6f2187d.f17ca8",
        "name": "sql",
        "func": "msg.head_code = 'y902';\nmsg.acq_point = msg.acq_points[msg.a];\nmsg.payload = `\n select * from ${msg.head_code}_${msg.acq_point} ;\n`;\nreturn msg;",
        "outputs": 1,
        "timeout": 0,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 350,
        "y": 340,
        "wires": [
            [
                "bd6adaa5521b32c0"
            ]
        ]
    },
    {
        "id": "adce2ab7a8392fbf",
        "type": "function",
        "z": "f6f2187d.f17ca8",
        "name": "res",
        "func": "msg.res = msg.payload;\nreturn msg;",
        "outputs": 1,
        "timeout": 0,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 730,
        "y": 340,
        "wires": [
            [
                "769962b26edf7b37"
            ]
        ]
    },
    {
        "id": "769962b26edf7b37",
        "type": "array-loop",
        "z": "f6f2187d.f17ca8",
        "name": "loop",
        "key": "r",
        "keyType": "msg",
        "reset": false,
        "resetValue": "value-null",
        "array": "res",
        "arrayType": "msg",
        "x": 890,
        "y": 340,
        "wires": [
            [
                "e9603cb7d3a5f412"
            ],
            [
                "2634b5563b822a61"
            ]
        ]
    },
    {
        "id": "2634b5563b822a61",
        "type": "function",
        "z": "f6f2187d.f17ca8",
        "name": "insert",
        "func": "const d = msg.res[msg.r];\nconst ts = getTime(d[0]);\nmsg.payload = `insert into tjdk.${msg.head_code}_${msg.acq_point} using tjdk.udf tags('${msg.head_code}','${msg.acq_point}') \n values('${ts}',${d[1]},${d[2]},${d[3]},${d[4]},${d[5]},${d[6]},${d[7]});`;\nreturn msg;\nfunction getTime(utc){\n// 一步到位:转时区 + 去掉T和Z\nconst res = new Date(new Date(utc).getTime() + 8 * 3600 * 1000).toISOString().replace(/T|Z/g, ' ').trim();\nreturn res;\n}",
        "outputs": 1,
        "timeout": 0,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 850,
        "y": 460,
        "wires": [
            [
                "886893fdf3103991"
            ]
        ]
    },
    {
        "id": "886893fdf3103991",
        "type": "taos-query",
        "z": "f6f2187d.f17ca8",
        "server": "216d9e608a07b6fd",
        "database": "tjdk",
        "sql": "",
        "x": 1020,
        "y": 460,
        "wires": [
            [
                "769962b26edf7b37"
            ]
        ]
    },
    {
        "id": "d0493f165da6620d",
        "type": "inject",
        "z": "f6f2187d.f17ca8",
        "name": "",
        "props": [
            {
                "p": "payload"
            },
            {
                "p": "topic",
                "vt": "str"
            }
        ],
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "topic": "",
        "payload": "",
        "payloadType": "date",
        "x": 170,
        "y": 240,
        "wires": [
            [
                "ca1fdb09be40fde9"
            ]
        ]
    },
    {
        "id": "ca1fdb09be40fde9",
        "type": "function",
        "z": "f6f2187d.f17ca8",
        "name": "acq_points",
        "func": "msg.acq_points = [\"rev\",\"temp\",\"electricity\",\"boilflow1\",\"boilflow2\",\"botemp\",\"gctemp\",\"uwttemp\",\"pwttemp\",\"crwflow\",\"sbflow\",\"eciwtemp\",\"ecowtemp\",\"ectflow\",\"ecpflow\",\"citemp\",\"trtemp\",\"tcatemp\",\"pcatemp\",\"vsxzl1\",\"ssxr1\",\"vsxzl2\",\"ssxr2\",\"cww2\",\"ewyield\",\"psizea\",\"psizeb\",\"psizec\",\"psized\",\"motorp\",\"motorr\",\"ttemp\",\"ptemp\",\"pdtemp1\",\"pdtemp2\",\"irwtemp\",\"pre\"]\nreturn msg;",
        "outputs": 1,
        "timeout": 0,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 350,
        "y": 240,
        "wires": [
            [
                "e9603cb7d3a5f412"
            ]
        ]
    },
    {
        "id": "e9603cb7d3a5f412",
        "type": "array-loop",
        "z": "f6f2187d.f17ca8",
        "name": "",
        "key": "a",
        "keyType": "msg",
        "reset": false,
        "resetValue": "value-null",
        "array": "acq_points",
        "arrayType": "msg",
        "x": 580,
        "y": 240,
        "wires": [
            [],
            [
                "63b02d7acafba141"
            ]
        ]
    },
    {
        "id": "bb86570570d747eb",
        "type": "taos-config",
        "host": "192.168.131.69",
        "port": "6041",
        "username": "root",
        "password": "taosdata"
    },
    {
        "id": "216d9e608a07b6fd",
        "type": "taos-config",
        "host": "192.168.131.125",
        "port": "6041",
        "username": "root",
        "password": "taosdata"
    }
]

八、批量删表

业务需求 : 因node-red数采bug,存入很多垃圾表,数量高达1000多万条;现在需要快速删除


#删除思路1:

#1 设置表显示的宽度,能看全表名称
SET MAX_BINARY_DISPLAY_WIDTH 500;

用node-red1次查询90万条数据存记事本/home/tables1.txt里面;

下载记事本到tdengine服务器,重命名为tables1.sql文件

然后执行  taos -f /home/tables1.sql

[
    {
        "id": "2da46befc37dee92",
        "type": "subflow",
        "name": "TDEngine",
        "info": "",
        "category": "",
        "in": [
            {
                "x": 60,
                "y": 200,
                "wires": [
                    {
                        "id": "3b9c3ab3a4380c46"
                    }
                ]
            }
        ],
        "out": [
            {
                "x": 380,
                "y": 200,
                "wires": [
                    {
                        "id": "3b9c3ab3a4380c46",
                        "port": 0
                    }
                ]
            }
        ],
        "env": [],
        "meta": {},
        "color": "#DDAA99"
    },
    {
        "id": "3b9c3ab3a4380c46",
        "type": "http request",
        "z": "2da46befc37dee92",
        "name": "[post /rest/sql]TD操作",
        "method": "POST",
        "ret": "obj",
        "paytoqs": "ignore",
        "url": "http://10.10.218.22:6041/rest/sql",
        "tls": "",
        "persist": false,
        "proxy": "",
        "insecureHTTPParser": false,
        "authType": "basic",
        "senderr": false,
        "headers": [],
        "x": 220,
        "y": 200,
        "wires": [
            []
        ]
    },
    {
        "id": "b5e3f97da4dba16d",
        "type": "inject",
        "z": "2ba8479c5ab1aeaf",
        "name": "",
        "props": [
            {
                "p": "payload"
            },
            {
                "p": "topic",
                "vt": "str"
            }
        ],
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "topic": "",
        "payload": "",
        "payloadType": "str",
        "x": 90,
        "y": 700,
        "wires": [
            [
                "8f391137131f2842"
            ]
        ]
    },
    {
        "id": "8f391137131f2842",
        "type": "function",
        "z": "2ba8479c5ab1aeaf",
        "name": "函数[sql]",
        "func": "msg.payload = `\n    SELECT table_name, create_time \n    FROM information_schema.ins_tables \n    WHERE db_name = 'tljd_datan' AND stable_name = 'datan'  and table_name like \"BX13%\"\n    AND LENGTH(table_name) > 30 limit 900000;\n`;\nreturn msg;",
        "outputs": 1,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 240,
        "y": 700,
        "wires": [
            [
                "3dac63b23d337757"
            ]
        ]
    },
    {
        "id": "3dac63b23d337757",
        "type": "subflow:2da46befc37dee92",
        "z": "2ba8479c5ab1aeaf",
        "name": "",
        "x": 420,
        "y": 700,
        "wires": [
            [
                "dce5b4dc73412231"
            ]
        ]
    },
    {
        "id": "dce5b4dc73412231",
        "type": "function",
        "z": "2ba8479c5ab1aeaf",
        "name": "处理",
        "func": "msg.data = [];\nmsg.flag = false;\nif (msg.payload && msg.payload.data.length > 0){\n    for (let d of msg.payload.data){\n        if (d[0].length > 25){\n            // msg.payload = `DROP TABLE tljd_datan.${d[0]};`;\n            // \n            msg.payload = `DROP TABLE tljd_datan.${d[0]};`;\n            node.send(msg);\n        }\n    }\n}\nnode.warn(\"开始执行:\" + msg.data.length);",
        "outputs": 1,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 590,
        "y": 700,
        "wires": [
            [
                "6188bad7ebbd5e32",
                "d345e1f6a4b61235"
            ]
        ]
    },
    {
        "id": "d345e1f6a4b61235",
        "type": "file",
        "z": "2ba8479c5ab1aeaf",
        "name": "",
        "filename": "/home/tables1.txt",
        "filenameType": "str",
        "appendNewline": true,
        "createDir": false,
        "overwriteFile": "false",
        "encoding": "none",
        "x": 810,
        "y": 700,
        "wires": [
            []
        ]
    }
]


#删除思路2:

利用以下的语句直接生成到sql里面,避免文件的导入导出了

弊端: 表名称显示不全; 有| 分隔符,类似日志,还需要处理,不建议使用

taos -s "SELECT CONCAT('DROP TABLE tljd_datan.', table_name, ';') drop_sql FROM information_schema.ins_tables WHERE db_name = 'tljd_datan' AND stable_name = 'datan' AND table_name like 'bx13%' AND LENGTH(table_name) > 30 limit 9;" > /home/tables1.sql

验证
#查询当前的表的垃圾表的个数

SELECT COUNT(*) total_count
FROM information_schema.ins_tables 
WHERE db_name = 'tljd_datan' 
  AND stable_name = 'datan'  
  AND table_name LIKE "BX13%"



 

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐