乐趣区

关于tdengine:TDengine-30-的-Update-有何区别

随着云原生时序数据库(Time Series Database,TSDB)TDengine 3.0 的公布,很多用户其实会好奇:“和 2.0 比起来,3.0 有哪些直观的优化呢?”

本文将以 Update 这一性能的变动为例,具体介绍一下 3.0 的粗疏优化。

和 2.0 比起来,3.0 版本的 Update 不再须要参数配置,“局部列更新”成为数据库自身的个性,并且还解决了 2.0 的 Update 机制的一些有余。

一、2.0 时代的 Update:

对于 TDengine 的 Update 性能,老用户应该都比较清楚:

在 2.0 版本中,TDengine 通过对 database 级别参数值“update”的配置,来实现对雷同工夫戳行的数据更新。

  1. update 为 0,不更新;
  2. update 为 1,整行更新,未指定值的列会被更新为 NULL;
  3. update 为 2,局部列更新,未指定值或者写入 NULL 的列会保留原有值。

一开始,TDengine 只反对 update 为 1(即整行更新)。但在很多场景下,用户往往不会在同一时间更新一张表中的所有列,因而咱们后续又反对了 update 为 2(即局部列更新)。

显然,局部列更新更为灵便,因为它既能够做到整行更新,又能够做到部分更新。然而通过它的逻辑,咱们或者会有这样的疑难:如果我想把一个值更新为 NULL 值,应该怎么办呢?这个疑难是有情理的。不过 2.0 版本并不反对这样的更新。

在 2.0 的版本中,数据能够被分为两大类 NORMAL 和 NULL。NORMAL 类代表 TDengine 所有数据类型中的非空值字面量,而 NULL 则代表所有数据类型的空值字面量。

当 Update 行为产生时,它的逻辑是:如果在某一行 insert 语句中没有显式写入某一列值的话,会认为该列输出了 NULL 值。

所以上面这两种写法的语义其实是一样的。

  1. insert into t1 (ts,num1,num2) values (“xxxx”,1,2) ;
  2. insert into t1 values (“xxxxx”,1,2,NULL) ;

所以在 update 为 1 时,上述两个 SQL 都会用 NULL 值会笼罩掉 num3 原有的值。

而在 update 为 2 时,上述两个 SQL 又都会保留 num3 原有的值。

因而,上述设定会导致 2.0 版本无奈把一个值更新为 NULL 值。

二、3.0 时代的 Update:

为了防止这一问题,从 3.0 版本开始,TDengine 引入了 None 值(未赋值)语义——当用户进行 insert 输出时,如果未对某一列进行显式输出(如下面的 SQL 语句 1),taosc 不再将其置为 NULL,而是将该列标识为 None(对外查问仍显示为 Null)。

因而,依然以上述两个 SQL 为例,在 3.0 版本的 Update 场景中,它们曾经有了不同:

  1. Insert into t1 (ts,num1,num2) values (“xxxxx”,1,2);(对于 num3 列, 标记为 NONE)
  2. insert into t1 values (“xxxxx”,1,2,NULL);(对于 num3 列, 标记为 NULL)

而 3.0 的 Update 规定为:如果写入的是 NORMAL/NULL,那么就取版本号比拟大的行,如果我写入的是 NONE,那么就取版本号比拟小的行,所以:

  • SQL 语句 1 会把 t1 表的 num1 和 num2 列都更新成最值,num3 放弃原样(因为 num3 要和 NONE 取版本比拟小的行);
  • SQL 语句 2 会把 t1 表的 num1 和 num2 列都更新成最值,num3 更新成 null(因为 num3 要和 NULL 取版本比拟大的行)。

由上可见,因为 NONE 的引入,3.0 曾经能够在无需任何配置的状况下,以局部列更新模式来进行数据更新了。

能够用这几条简略的 SQL 来体验 TDengine 的这个新个性:

CREATE TABLE `t1` (`ts` TIMESTAMP, `num1` INT, `num2` INT, `num3` INT);
insert into t1 values ("2020-01-01 01:00:00",1,1,1);
insert into t1 (ts,num1,num2) values ("2020-01-01 01:00:00",2,2);
insert into t1 values ("2020-01-01 01:00:00",3,3,null);

三、更新逻辑

其实,TDengine 不论是在 2.0 还是 3.0 时代,更新的逻辑都是相似的:3.0 是不管在硬盘还是内存的数据都只是标记更新(写入工夫戳雷同的数据会生成子数据块),而 2.0 内存中的数据是物理更新,硬盘上是标记更新。在查问的时候,他们都是先把本来的数据块和子数据块从硬盘上读取到内存中,再通过被高版本笼罩或被低版本笼罩的形式实现某列数据的更新或保留,而后再把它们与原先存在于内存中的数据合并解决,最初把后果返回给客户端。

不过,与 2.0 比起来,3.0 应用了 multi-version(多版本模式),这是因为 2.0 的更新、删除性能不是一开始就有的,而是前期逐渐减少的实现,有点像打补丁,不够优雅。所以 3.0 相当于把这些割裂的性能,从存储引擎底部做了一次优化交融,也大幅晋升了用户体验,以这个 Update 性能为例,用户不再须要任何配置,只须要晓得 TDengine 的更新形式就能够了。

而对于 3.0 的存储引擎的底层优化具体详情,能够通过这篇文章进一步理解。

四、结语

3.0 上有很多相似这样的优化和重构。之后咱们会继续以文章视频等模式,率领大家深刻摸索这款云原生的时序数据库,一起为企业带来价值,为开发者带来胜利。

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

退出移动版