乐趣区

关于tdengine:TDengine-如何进行-SQL-写入官方最全教程来了

小 T 导读:为应答不同场景下的写入需要,TDengine 共提供了四种写入协定,其中最罕用的当属 SQL 写入了,为了让大家在理论写入操作时更加不便,咱们整顿了一篇具体解读 SQL INSERT 语法规定的文章。倡议提前珍藏,有须要时可随时参考。

在诸多时序数据库(Time Series Database)中,如果能反对 SQL,则能够大大降低用户的学习和接入老本,而 TDengine 正是这样一款产品。

TDengine SQL 是供应用户进行数据写入和查问的次要工具。为了便于用户疾速上手,它在肯定水平上与规范 SQL 格调和模式相似。因为 TDengine 的晚期版本没有提供时序数据的删除性能,因而其 SQL 语法也没有提供数据删除的相干性能。不过从 TDengine 企业版从 2.6 开始提供了 DELETE 语句。

为更好地阐明 SQL 语法的规定及其特点,本文假如存在一个数据集。以智能电表(meters)为例,假如每个智能电表采集电流、电压和相位三个量。其建模如下:

taos> DESCRIBE meters;
             Field              |        Type        |   Length    |    Note    |
=================================================================================
 ts                             | TIMESTAMP          |           8 |            |
 current                        | FLOAT              |           4 |            |
 voltage                        | INT                |           4 |            |
 phase                          | FLOAT              |           4 |            |
 location                       | BINARY             |          64 | TAG        |
 groupid                        | INT                |           4 | TAG        |

创立超级表和字表的语句可参考 TDengine 官网的官网文档。

以上数据集蕴含 4 个智能电表的数据,依照 TDengine 的建模规定,对应 4 个子表,其名称别离是 d1001、d1002、d1003 以及 d1004。上面咱们将以此模型为例,详解 TDengine 中的 SQL INSERT 语法规定。写入语法如下:

INSERT INTO
    tb_name
        [USING stb_name [(tag1_name, ...)] TAGS (tag1_value, ...)]
        [(field1_name, ...)]
        VALUES (field1_value, ...) [(field1_value2, ...) ...] | FILE csv_file_path
    [tb2_name
        [USING stb_name [(tag1_name, ...)] TAGS (tag1_value, ...)]
        [(field1_name, ...)]
        VALUES (field1_value, ...) [(field1_value2, ...) ...] | FILE csv_file_path
    ...];

插入一条或多条记录

首先咱们须要先指定一个曾经创立好的数据子表的表名,并通过 VALUES 关键字提供一行或多行数据,即可向数据库写入这些数据。例如,执行如下语句能够写入一行记录:

INSERT INTO d1001 VALUES (NOW, 10.2, 219, 0.32);

或者,能够通过如下语句写入两行记录:

INSERT INTO d1001 VALUES ('2021-07-13 14:06:32.272', 10.2, 219, 0.32) (1626164208000, 10.15, 217, 0.33);

在此过程中,须要留神以下三点:

  1. 在第二个代码示例中,两行记录的首列工夫戳应用了不同格局的写法。其中字符串格局的工夫戳写法不受所在 Database 的工夫精度设置影响;而长整形格局的工夫戳写法会受到所在 Database 的工夫精度设置影响——例子中的工夫戳在毫秒精度下能够写作 1626164208000,而如果是在微秒精度设置下就须要写为 1626164208000000,纳秒精度设置下须要写为 1626164208000000000。
  2. 在应用“插入多条记录”形式写入数据时,不能把第一列的工夫戳取值都设为 NOW,否则会导致语句中的多条记录应用雷同的工夫戳,就可能呈现互相笼罩以至这些数据行无奈全副被正确保留的危险。其起因在于,NOW 函数在执行中会被解析为所在 SQL 语句的理论执行工夫,呈现在同一语句中的多个 NOW 标记也就会被替换为完全相同的工夫戳取值。
  3. 容许插入的最老记录的工夫戳,认定规范是用以后服务器工夫减去配置的 keep 值(数据保留的天数);容许插入的最新记录的工夫戳,认定规范是用以后服务器工夫加上配置的 days 值(数据文件存储数据的时间跨度,单位为天)。keep 和 days 都是能够在创立数据库时指定的,缺省值别离是 3650 天和 10 天。

插入记录,数据对应到指定的列

当咱们向数据子表中插入记录时,无论插入一行还是多行,都能够让数据对应到指定的列。对于 SQL 语句中没有呈现的列,数据库将主动填充为 NULL。但要留神主键(工夫戳)不能为 NULL。例如:

INSERT INTO d1001 (ts, current, phase) VALUES ('2021-07-13 14:06:33.196', 10.27, 0.31);

如果不指定列,即应用全列模式,那么在 VALUES 局部提供的数据,必须为数据表的每个列都显式地提供数据。全列模式写入速度会远快于指定列,因而倡议尽可能采纳全列写入形式,此时空列能够填入 NULL。

向多个表插入记录

能够在一条语句中,别离向多个表插入一条或多条记录,并且也能够在插入过程中指定列。例如:

INSERT INTO d1001 VALUES ('2021-07-13 14:06:34.630', 10.2, 219, 0.32) ('2021-07-13 14:06:35.779', 10.15, 217, 0.33)
            d1002 (ts, current, phase) VALUES ('2021-07-13 14:06:34.255', 10.27, 0.31);

也能够在主动建表时,只是指定局部 TAGS 列的取值,未被指定的 TAGS 列将置为 NULL。例如:

INSERT INTO d21001 USING meters (groupId) TAGS (2) VALUES ('2021-07-13 14:06:33.196', 10.15, 217, 0.33);

主动建表语法也反对在一条语句中向多个表插入记录。例如:

INSERT INTO d21001 USING meters TAGS ('California.SanFrancisco', 2) VALUES ('2021-07-13 14:06:34.630', 10.2, 219, 0.32) ('2021-07-13 14:06:35.779', 10.15, 217, 0.33)
            d21002 USING meters (groupId) TAGS (2) VALUES ('2021-07-13 14:06:34.255', 10.15, 217, 0.33)
            d21003 USING meters (groupId) TAGS (2) (ts, current, phase) VALUES ('2021-07-13 14:06:34.255', 10.27, 0.31);

如果利用的是 2.0.20.5 之前的版本,那在应用主动建表语法并指定列时,子表的列名必须紧跟在子表名称前面,而不能如例子里那样放在 TAGS 和 VALUES 之间。从 2.0.20.5 版本开始,这两种写法都能够应用了,但也不能在一条 SQL 语句中混用,否则会报语法错误。

插入来自文件的数据记录

在进行文件的数据记录插入时,除了应用 VALUES 关键字插入一行或多行数据外,也能够把要写入的数据放在 CSV 文件中(英文逗号分隔、英文单引号括住每个值)供 SQL 指令读取,其中 CSV 文件无需表头。例如,如果 /tmp/csvfile.csv 文件的内容为:

'2021-07-13 14:07:34.630', '10.2', '219', '0.32'
'2021-07-13 14:07:35.779', '10.15', '217', '0.33'

那么通过如下指令能够把这个文件中的数据写入子表中:

INSERT INTO d1001 FILE '/tmp/csvfile.csv';

如果想要执行主动建表,从 2.1.5.0 版本开始,就曾经反对在插入来自 CSV 文件的数据时,以超级表为模板来主动创立不存在的数据表。例如:

INSERT INTO d21001 USING meters TAGS ('California.SanFrancisco', 2) FILE '/tmp/csvfile.csv';

历史记录写入

在进行历史数据写入时,咱们可应用 IMPORT 或者 INSERT 命令。因为 IMPORT 的语法、性能与 INSERT 齐全一样,上面咱们就以 INSERT 来阐明。

针对 INSERT 类型的 SQL 语句,咱们采纳的是流式解析策略,在发现前面的谬误之前,后面正确的局部 SQL 仍会执行。上面的 SQL 中,INSERT 语句是有效的,然而 d1001 仍会被创立。

taos> CREATE TABLE meters(ts TIMESTAMP, current FLOAT, voltage INT, phase FLOAT) TAGS(location BINARY(30), groupId INT);
Query OK, 0 row(s) affected (0.008245s)
taos> SHOW STABLES;
              name              |      created_time       | columns |  tags  |   tables    |
============================================================================================
 meters                         | 2020-08-06 17:50:27.831 |       4 |      2 |           0 |
Query OK, 1 row(s) in set (0.001029s)
taos> SHOW TABLES;
Query OK, 0 row(s) in set (0.000946s)
taos> INSERT INTO d1001 USING meters TAGS('California.SanFrancisco', 2) VALUES('a');
DB error: invalid SQL: 'a' (invalid timestamp) (0.039494s)
taos> SHOW TABLES;
           table_name           |      created_time       | columns |          stable_name           |
======================================================================================================
 d1001                          | 2020-08-06 17:52:02.097 |       4 | meters                         |
Query OK, 1 row(s) in set (0.001091s)

写在最初

家喻户晓,传统 database 是把整个 SQL 语句发送到服务端,由服务端实现所有的解决逻辑。和传统数据库不同的是,TDengine 会在客户端实现大部分解决逻辑。在语法解析阶段,因为状态机解析 SQL 效率不高,因而针对插入,TDengine 顺便设计了流式解析;此外,对于蕴含表 schema 信息和表所在 dnode 的 table meta,会在客户端进行缓存,之后只须要从本地 cache 中获取即可,为了能在服务端实现高效解决,还会在客户端对每个 table 的数据进行排序和去重……

这些在设计上的诸多细节,也让 TDengine 实现了高效的数据写入。值得一提的是,为了满足局部客户对性能的极其要求,TDengine 还开发了 stmt 接口,进一步加重语法解析带来的性能问题,目前通过多个用户的线上实际佐证,性能至多进步了 4~5 倍,欢送大家试用。

如果你还有对于 SQL 写入的更多问题,能够移步至 TDengine 官网上的技术文档中查看更多代码细节,也欢送进入官网社群,寻求社区技术人员的帮忙。


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

退出移动版