乐趣区

关于数据库:写给关系数据库开发者的-TDengine-入门指南

MySQL 是中国开发者最相熟的开源数据库产品,在很多开发者心中 MySQL 就是关系数据库的代名词。开发者们对 MySQL 数据库的的个性曾经十分相熟了。

TDengine(https://github.com/taosdata/T…)是齐全面向解决时序数据而设计的数据库,是数据库畛域的“新物种”,也就是所谓的时序数据库(Time Series Database,简称 TSDB)。TDengine 在创建伊始,就动摇地走兼容 SQL 的路线,这极大地升高了数据库用户的应用门槛,然而另一方面,时序数据和关系数据库的解决形式还是有些区别,所以相熟 MySQL 的用户在动手 TDengine 的时候会有一些混同。所以,咱们专门撰写了这篇文章,心愿能够帮忙宽广相熟 MySQL 数据库的开发者更快地上手 TDengine。

但同时咱们也要指出,TDengine 是专门为解决时序数据而设计的产品,并不适宜存储非时序类型数据,在理论利用中,能够联合关系型数据库一起应用。

注:本文以最新的 TDengine 3.0.1.4 版本为例。

时序数据建模

用 MySQL 关系型数据库给时序数据建模

为了不便大家了解,咱们先用大家相熟的关系型数据库进行建模。建模的场景是咱们要采集一万个电表的数据,每个电表有本人的设施 ID(device_id),有所在的地位(location),电表有不同型号(group_id)。每次采集咱们要记录过后的工夫戳(ts)、电表的电流(current)、电压(voltage)、相位(phase)三个数据。

创立数据库的 SQL 语句:
CREATE SCHEMA test;

表 meters

创立表 meters 的 SQL 语句:

CREATE TABLE `test`.`meters` (`device_id` VARCHAR(8) NOT NULL,
  `ts` TIMESTAMP(3) NOT NULL,
  `current` FLOAT NULL,
  `voltage` INT NULL,
  `phase` FLOAT NULL,
  PRIMARY KEY (`device_id`, `ts`),
  CONSTRAINT `FK_meters_devices`
    FOREIGN KEY (`device_id`)
    REFERENCES `test`.`devices` (`device_id`));

表 devices

创立表 devices 的 SQL 语句:

CREATE TABLE `test`.`devices` (`device_id` VARCHAR(8) NOT NULL,
  `location` VARCHAR(24) NOT NULL,
  `group_id` INT NOT NULL,
  PRIMARY KEY (`device_id`),
  INDEX `IDX_location` (`location` ASC),
  INDEX `IDX_group_id` (`group_id` ASC));

把 MySQL 建模转换成 TDengine 建模

咱们来比照看看 TDengine 的建模和 MySQL 有什么不同。让咱们先引入 TDengine 的两个概念:

1、一个设施采集点一张表

依据这一设计,device_id 就是子表名称。location 和 group_id 咱们作为子表的 TAG。主键:在 TDengine 中,表的第一个字段必须是 TIMESTAMP 类型,并且会被主动设置为主键。

2、超级表与子表

在一个设施采集点一张表的设计理念下,对应设施的数量,会呈现成千上万乃至上亿张表,TDengine 为此又引入了“超级表”和“子表”两个概念,它们有如下几个次要特色:

  • 超级表是子表的模板,定义了子表的数据结构,所有子表都是由超级表“派生”进去,批改超级表构造就是批改所有子表构造;
  • 基于超级表能够轻松进行分组聚合查问,查出每个子表的聚合计算后的数据,如:查问每个电表的总用电量;
  • 标签(TAG)能够了解为定义在超级表中的字段,每一个子表只有一组标签值,代表一个采集点的静态数据且为内存存储。在 SELECT 语句查问的时候,标签(TAG)值能够像一般字段一样呈现在查问后果中。

更多 TDengine 超级表文档请参考:https://docs.taosdata.com/tao…。

当初让咱们用 TDengine 进行建模,创立数据库的 SQL 语句:
CREATE DATABASE test;
而后创立一张超级表:

表 meters

创立表 metrics 的 SQL 语句:

CREATE STABLE `test`.`meters` (
  `ts` TIMESTAMP,
  `current` FLOAT,
  `voltage` INT,
  `phase` FLOAT)
TAGS (
  `group_id` INT,
  `location` VARCHAR(24));

对于数据类型的比照

TDengine 数据类型文档请参考:https://docs.taosdata.com/tao…。

关键字和保留词

MySQL 和 TDengine 的关键字 / 保留词略有不同,所以有些状况下创立表名、字段名时候,须要留神加上反引号“进行本义。举例:

  • TTL 在 TDengine 中是关键字,但在 MySQL 中不是。
  • CURRENT 在 MySQL 中是关键字,但在 TDengine 中不是。

数据插入与更新

上面让咱们来体验下数据处理的实在例子:

插入采集数据

MySQL

插入设施数据

依照下面的建模,MySQL 插入数据之前,须要先筹备好设施数据,上面咱们筹备几条:

INSERT INTO `test`.`devices` VALUES ('d1001', 'California.SanFrancisco', 2);
INSERT INTO `test`.`devices` VALUES ('d1002', 'California.SanFrancisco', 3);
INSERT INTO `test`.`devices` VALUES ('d1003', 'California.LosAngeles', 3);

插入采集数据

INSERT INTO `test`.`meters` VALUES ('d1001', '2018-09-08 17:51:04.777', 10.3, 219, 0.31);
INSERT INTO `test`.`meters` VALUES ('d1002', '2018-09-08 17:51:04.777', 10.2, 220, 0.23);
INSERT INTO `test`.`meters` VALUES ('d1003', '2018-09-08 17:51:04.777', 11.5, 221, 0.35);

TDengine

创立子表

因为 TDengine 的设施属性通过标签(TAG)的形式表白,所以在创立子表的时候来定义设施的属性(对应 MySQL 的插入设施数据)。让咱们先来创立子表:

CREATE TABLE `test`.`d1001` USING `test`.`meters` (`group_id`, `location`) TAGS (2, "California.SanFrancisco");
CREATE TABLE `test`.`d1002` USING `test`.`meters` (`group_id`, `location`) TAGS (3, "California.SanFrancisco");
CREATE TABLE `test`.`d1003` USING `test`.`meters` (`group_id`, `location`) TAGS (3, "California.LosAngeles");

以上语句的语义是通过应用(USING)超级表 test.meters,来创立对应标签(TAGS)的子表。
**
插入采集数据 **

INSERT INTO `test`.`d1001` VALUES ('2018-09-08 17:51:04.777', 10.3, 219, 0.31);
INSERT INTO `test`.`d1001` VALUES ('2018-09-08 17:51:04.777', 10.2, 220, 0.23);
INSERT INTO `test`.`d1001` VALUES ('2018-09-08 17:51:04.777', 11.5, 221, 0.35);

插入采集数据时主动创立子表

TDengine 还有更便捷的形式,能够让创立子表和插入数据在同一条语句中实现:

INSERT INTO `test`.`d1001` USING `test`.`meters` TAGS ('California.SanFrancisco', 2) VALUES ('2018-09-08 17:51:04.777', 10.3, 219, 0.31);

对于写入数据的具体文档,请参考:https://docs.taosdata.com/tao…。

更新采集数据

MySQL

咱们先来看看 MySQL 如何更新数据:

更新采集数据:

UPDATE `test`.`meters` SET `ts` = '2018-09-08 17:51:07', `current` = 10.4, `voltage` = 220, `phase` = 0.32 WHERE `device_id` = 'd1001' and `ts` = '2018-09-08 17:51:05';

TDengine

TDengine 中没有 UPDATE 语句,然而 TDengine 也反对更新。在 TDengine 中,INSERT 工夫戳雷同的数据,会更新原有记录:

INSERT INTO `test`.`d1001` VALUES ('2018-09-08 17:51:04.777', 10.4, 225, 0.35);

留神:TDengine 2.x 版本须要在创立数据库时指定 UPDATE 参数,3.x 版本不须要。

更新设施属性

MySQL

咱们先来看看 MySQL 建模下如何更新设施属性:

UPDATE `test`.`devices` SET `location` = 'California.LosAngeles', `group_id` = 3 WHERE `device_id` = 'd1001';

TDengine

如前文所述,TDengine 的设施属性存在于标签(TAG)之中,批改设施属性就是批改标签,所以要用批改标签的语句:

ALTER TABLE `test`.`d1001` SET TAG `location` = 'California.LosAngeles';
ALTER TABLE `test`.`d1001` SET TAG `group_id` = 5;

注:标签只可单个批改。

工具与可视化

GUI 工具

MySQL 官网从 5.0 版本开始提供了 MySQL Workbench 这个图形管理工具,目前 TDengine 还未提供官网的 GUI 管理工具,然而因为 TDengine 反对 JDBC 规范驱动,这就让 TDengine 能够通过 JDBC 驱动间接对接目前市面上大量的 SQL IDE 产品,比方 DBeaver、IDEA 等。TDengine 官网也提供了相干文档,供参考:
如何通过开源数据库管理工具 DBeaver 连贯 TDengine

如何通过 IDEA 数据库管理工具连贯 TDengine?

此外,TDengine 企业版提供了 Taos Explorer,提供专门适配 TDengine 技术架构的残缺 GUI 管理工具。如果你想应用 Taos Explorer,也能够间接分割官网企业咨询服务:https://www.taosdata.com/support。

可视化

TDengine 官网曾经适配了 Grafana,在 Grafana 官网插件库里能够找到,详情请参考 TDengine 官网文档:https://docs.taosdata.com/thi…。

导入导出工具

MySQL 官网提供了 mysqldump 工具用来进行数据的导入和导出。同样的,TDengine 官网也提供了 taosdump 工具来进行雷同的工作。详情请参考官网文档:https://docs.taosdata.com/ope… 和 https://docs.taosdata.com/ope…。

容量与查问性能比照

环境与数据筹备

设施环境:MacBook Pro 14 M1 8-core 16GB

MySQL 版本:8.0.28

TDengine 版本:3.0.1.4

咱们通过应用 taosBenchmark 工具(https://docs.taosdata.com/ref…),来随机生成一亿条采集数据,散布在一张超级表 meters 下的一万张子表中,并把雷同的数据按上述建模模型导入进 MySQL,确保最初的比对后果统一。

存储空间比照

针对上述数据,MySQL 理论存储空间为 4,931 MB,TDengine 存储空间为 493 MB。

查问性能比照

典型查问一(COUNT)

SELECT COUNT(*) FROM test.meters;

MySQL

TDengine

总结:TDengine 查问性能是 MySQL 的 50 倍

典型查问二(平均值,最大值、最小值)

SELECT AVG(voltage) FROM `test`.`meters`;
SELECT MAX(voltage) FROM `test`.`meters`;
SELECT MIN(voltage) FROM `test`.`meters`;

注:通过测试,MySQL 和 TDengine 对 AVG()、MAX()、MIN() 函数的查问工夫均相似,所以不再额定展现。

MySQL

TDengine

典型查问三(条件查问)

MySQL

SELECT COUNT(*) FROM `test`.`meters` m INNER JOIN `test`.`devices` d ON m.device_id = d.device_id WHERE d.location = "California.MountainView";

TDengine

SELECT COUNT(*) FROM `test`.`meters` WHERE location = "California.MountainView";

典型查问四(分组查问)

MySQL

SELECT AVG(m.voltage), d.location FROM `test`.`meters` m INNER JOIN `test`.`devices` d ON m.device_id = d.device_id GROUP BY d.location;

TDengine

SELECT AVG(voltage), location FROM `test`.`meters` GROUP BY location;

典型查问五(时序业务)

MySQL

SELECT DATE_FORMAT(ts, '%Y%m%d-%H') AS date_format, AVG(voltage) FROM `test`.`meters` GROUP BY date_format;

TDengine

SELECT AVG(voltage) FROM `test`.`meters` INTERVAL(1h);

TDengine 的特色性能(时序数据处理)

TDengine 在反对规范 SQL 的根底之上,还提供了一系列满足时序业务场景需要的特色查问语法,这些语法可能为时序场景的利用的开发带来极大的便当。

工夫窗口切分查问

TDengine 反对按工夫窗口切分形式进行聚合后果查问,比方需查问每隔 1 秒钟的电流平均值。举例:

SELECT _wstart, AVG(current) FROM `test`.`d1001` INTERVAL(1s);

状态窗口切分查问

应用整数(布尔值)或字符串来标识产生记录时候设施的状态量。产生的记录如果具备雷同的状态量数值则归属于同一个状态窗口,数值扭转后该窗口敞开。举例:

SELECT COUNT(*), FIRST(ts), voltage FROM `test`.`meters` STATE_WINDOW(voltage) LIMIT 10;

数据保留策略

通过长时间累积大量数据当前,历史数据往往须要做归档或删除解决。MySQL 等关系型数据库只能通过执行打算工作调用 DELETE 语句依据工夫条件删除数据。而 TDengine 天生就对数据保留策略提供了反对,一共有三种方法来灵便地解决:

  • 创立数据库时,设定 KEEP 参数,比方 CREATE DATABASE test KEEP 100d; 示意数据库中的数据在保留 100 天后会被主动删除;
  • 创立表时,设定 TTL 参数,单位为天,比方 CREATE TABLE meters … TTL 50; 示意 50 天之后,表会被零碎主动删除;
  • 冷热数据分级存储。在 TDengine 企业版中,反对把数据依照工夫维度别离存储于不同的文件句柄,能够对应到不同的存储介质,比方将热数据存储于 SSD 磁盘,将冷数据存储到 S3 存储中。

代替 MySQL 案例分享

事实证明,在时序数据场景下,无论是在存储空间、写入速度还是查问性能等各方面,TDengine 都存在数量级劣势。最初,提供一些应用新一代时序数据库 TDengine 代替传统关系性数据库 MySQL 的典型案例供参考:

  • 存储空间降为 MySQL 的十分之一,TDengine 在货拉拉数据库监控场景的利用
  • MySQL 无奈满足查问性能?北今天时抉择 TDengine 实现热网监控和能源剖析
  • 接手被 MySQL 卡死的数据,TDengine 在能源管理系统的利用
  • MySQL 宕机?大数据驱动下的新批发,如何寻求存储计算的最优解?

欢送增加小 T(VX:TDengine),退出物联网技术探讨群,第一工夫理解 TDengine 官网信息,与关注前沿技术的同学们独特探讨新技术、新玩法。


想理解更多 TDengine Database 的具体细节,欢送大家在 GitHub 上查看相干源代码。

退出移动版