图数据库 Nebula Graph TTL 特性

身处在如今这个大数据时代,咱们处理的数据量需以 TB、PB, 甚至 EB 来计算,怎么处理庞大的数据集是从事数据库领域人员的共同问题。解决这个问题的核心在于,数据库中存储的数据是否都是有效的、有用的数据,所以如何提升数据中有效数据的利用率、将无效的过时数据清洗掉,便成了数据库领域的一个热点话题。在本文中咱们将着重讲述如何在数据库中处理过时数据这一问题。mysql

在数据库中清洗过时数据的方式多种多样,好比存储过程、事件等等。在这里笔者举个例子来简要说明 DBA 常用的存储过程 + 事件来清理过时数据的过程。sql

存储过程 + 事件清洗数据

存储过程(procedure)

存储过程是由一条或多条 SQL 语句组成的集合,当对数据库进行一系列的读写操做时,存储过程可将这些复杂的操做封装成一个代码块以便重复使用,大大减小了数据库开发人员的工做量。一般存储过程编译一次,能够执行屡次,所以也大大的提升了效率。数据库

存储过程有如下优势:安全

  • 简化操做,将重复性很高的一些操做,封装到一个存储过程当中,简化了对这些 SQL 的调用数据结构

  • 批量处理,SQL + 循环,减小流量,也就是“跑批”app

  • 统一接口,确保数据的安全ide

  • 一次编译屡次执行,提升了效率。函数

以 MySQL 为例,假如要删除数据的表结构以下:性能

mysql> SHOW CREATE TABLE person;
+--------+---------------------------------------------------------------------------------------------------------------------------------+
| Table  | Create Table                                                                                                                    |
+--------+---------------------------------------------------------------------------------------------------------------------------------+
| person | CREATE TABLE `person` (
  `age` int(11) DEFAULT NULL,
  `inserttime` datetime DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8 |
+--------+---------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

建立一个名为 person 的表,其中 inserttime 字段为 datetime 类型,咱们用 inserttime 字段存储数据的生成时间。大数据

建立一个删除指定表数据的存储过程,以下:

mysql> delimiter //

mysql> CREATE PROCEDURE del_data(IN `date_inter` int)
    -> BEGIN
    ->   DELETE FROM person WHERE inserttime < date_sub(curdate(), interval date_inter day);
    -> END //

mysql> delimiter ;

建立一个名为 del_data 的存储过程,参数 date_inter 指定要删除的数据距离当前时间的天数。当表 person 的 inserttime 字段值(datetime 类型)加上参数 date_inter 天小于当前时间,则认为数据过时,将过时的数据删除。

事件(event)

事件是在相应的时刻调用的过程式数据库对象。一个事件可调用一次,也可周期性的启动,它由一个特定的线程来管理,也就是所谓的“事件调度器”。<br />事件和触发器相似,都是在某些事情发生的时候启动。当数据库上启动一条语句的时候,触发器就启动了,而事件是根据调度事件来启动的。因为它们彼此类似,因此事件也称为临时性触发器。事件调度器能够精确到每秒钟执行一个任务。

以下建立一个事件,周期性的在某个时刻调用存储过程,来进行清理数据。

mysql> CREATE EVENT del_event  
    ->     ON SCHEDULE 
    ->     EVERY 1 DAY 
    ->     STARTS '2020-03-20 12:00:00'
    ->     ON COMPLETION PRESERVE ENABLE
    ->     DO CALL del_data(1);

建立一个名为 del_event 的事件,该事件从 2020-03-20 开始,天天的 12:00:00 执行存储过程 del_data(1)。

而后执行:

mysql> SET global event_scheduler = 1;

打开事件。这样事件 del_event 就会在指定的时间自动在后台执行。经过上述的存储过程 del_data 和事件 del_event,来达到定时自动删除过时数据的目的。

TTL(Time To Live) 清洗数据

经过上述存储过程和事件的组合能够定时清理数据库中的过时数据。图数据库 Nebula Graph 提供了更加简单高效的方式--使用 TTL 的方式来自动清洗过时数据

使用 TTL 方式自动清洗过时数据的好处以下:

  1. 简单方便

  2. 经过数据库系统内部逻辑进行处理,安全可靠<br />

  3. 数据库会根据自身的状态自动判断是否须要处理,若是须要处理,将在后台自动进行处理,无需人工干预。

TTL 简介

TTL,全称 Time To Live,用来指定数据的生命周期,数据时效到期后这条数据会被自动删除。在图数据库 Nebula Graph 中,咱们实现 TTL 功能,用户设置好数据的存活时间后,在预约时间内系统会自动从数据库中删除过时的点或者边。

在 TTL 中,过时数据会在下次 compaction 时被删除,在下次 compaction 以前,query 会过滤掉过时的点和边。

图数据库 Nebula Graph 的 TTL 功能需 ttl_col  和 ttl_duration 两个字段一块儿使用,到期阈值是 ttl_col 指定的属性对应的值加上 ttl_duration  设置的秒数。其中 ttl_col 指定的字段的类型应为 integer 或 timestamp,ttl_duration 的计量单位为秒。

TTL 读过滤

针对 tag / edge,Nebula Graph 在 TTL 中将读数据过滤逻辑下推到 storage 层进行处理。在 storage 层,首先获取该 tag / edge 的 TTL 信息,而后依次遍历每一个顶点或边,取出 ttl_col 字段值,根据 ttl_duration 的值加上 ttl_col 列字段值,跟当前时间的时间戳进行比较,判断数据是否过时,过时的数据将被忽略。

TTL compaction

RocksDB 文件组织方式

图数据库 Nebula Graph 底层存储使用的是 RocksDB,RocksDB 在磁盘上的文件是分为多层的,默认是 7 层,以下图所示:

SST文件在磁盘上的组织方式

Level 0 层包含的文件,是由内存中的 Memtable flush 到磁盘,生成的 SST 文件,单个文件内部按 key 有序排列,文件之间无序。其它 Level 上的多个文件之间都是按照 key 有序排列,而且文件内也有序,以下图所示:

非Level 0 层的文件数据划分

RocksDB compaction 原理

RocksDB 是基于 LSM 实现,但 LSM 并非一个具体的数据结构,而是一种数据结构的概念和设计思想,具体细节参考LSM论文。而 LSM 中最重要部分就是 compaction,因为数据文件采用 Append only 方式写入,而对于过时的数据,重复的、已删除的数据,须要经过 compaction 进行逐步的清理。<br />

RocksDB compaction 逻辑

咱们采用的 RocksDB 的 compaction 策略为 Level compaction。当数据写到 RocksDB 时,会先将数据写入到一个 Memtable 中,当一个 Memtable 写满以后,就会变成 Immutable 的 Memtable。RocksDB 在后台经过一个 flush 线程将这个 Memtable flush 到磁盘,生成一个 Sorted String Table (SST) 文件,放在 Level 0 层。当 Level 0 层的 SST 文件个数超过阈值以后,就会与Level 1 层进行 compaction。一般必须将 Level 0 的全部文件 compaction 到 Level 1 中,由于 Level 0 的文件的 key 是有交叠的。

Level 0 与 Level 1 的 compaction 以下:

Level 0 与 Level 1 的 compaction

其余 Level 的 compaction 规则同样,以 Level 1与 Level 2 的 compaction 为例进行说明,以下所示:

Level 1 与 Level 2 的 compaction

当 Level 0 compaction 完成后,Level 1 的文件总大小或者文件数量可能会超过阈值,触发 Level 1 与 Level 2 的 compaction。从 Level 1 层至少选择一个文件 compaction 到 Level 2 的 key 重叠的文件中。compaction 后可能会触发下一个 Level 的 compaction,以此类推。

若是没有 compaction,写入是很是快的,但这样会形成读性能下降,一样也会形成很严重的空间放大问题。为了平衡写入、读取、空间三者的关系,RocksDB 会在后台执行 compaction,将不一样 Level 的 SST 进行合并。

TTL compaction 原理

除了上述默认的compaction操做外(sst文件合并),RocksDB 还提供了CompactionFilter 功能,可让用户自定义个性化的compaction逻辑。Nebula Graph 使用了这个CompactionFilter来定制本文讨论的TTL功能。该功能是 RocksDB 在 compaction 过程当中,每读取一条数据时,都会调用一个定制的Filter 函数。TTL compaction 的实现方法就是在 Filter 函数中实现 TTL 过时数据删除逻辑,具体以下:

  1. 首先获取 tag / edge 的 TTL 信息

  2. 而后遍历每一个顶点或边数据,取出 ttl_col 列字段值

  3. 根据 ttl_duration 的值加上 ttl_col 列字段值,跟当前时间的时间戳进行比较,而后判断数据是否过时,过时的数据将被删除。

TTL 用法

在图数据库 Nebula Graph 中,edge 和 tag 实现逻辑一致,在这里仅以 tag 为例,来介绍 Nebula Graph 中 TTL 用法。

建立 TTL 属性

Nebula Graph 中使用 TTL 属性分为两种方式:

create tag 时指定 ttl_duration 来表示数据的持续时间,单位为秒。ttl_col 指定哪一列做为 TTL 列。语法以下:

nebula> CREATE TAG t (id int, ts timestamp ) ttl_duration=3600, ttl_col="ts";

当某一条记录的 ttl_col 列字段值加上 ttl_duration 的值小于当前时间的时间戳,则该条记录过时,不然该记录不过时。

  • ttl_duration 的值为非正数时,则点的此 tag 属性不会过时

  • ttl_col 只能指定类型为 int 或者 timestamp 的列名。郑州哪家不孕不育医院好:http://www.zztjby.com/

或者 create tag 时没有指定 TTL 属性,后续想使用 TTL 功能,可使用 alter tag 来设置 TTL 属性。语法以下:

nebula> CREATE TAG t (id int, ts timestamp );
nebula> ALTER TAG t ttl_duration=3600, ttl_col="ts";

查看 TTL 属性

建立完 tag 可使用如下语句查看 tag 的 TTL 属性:

nebula> SHOW CREATE TAG t;
=====================================
| Tag | Create Tag                  |
=====================================
| t   | CREATE TAG t (
  id int,
  ts timestamp
) ttl_duration = 3600, ttl_col = id |
-------------------------------------

修改 TTL 属性

可使用 alter tag 语句修改 TTL 的属性:

nebula> ALTER TAG t ttl_duration=100, ttl_col="id";

删除 TTL 属性

当不想使用 TTL 属性时,能够删除 TTL 属性:

能够设置 ttl_col 字段为空,或删除配置的 ttl_col 字段,或者设置 ttl_duration 为 0 或者 -1。

nebula> ALTER TAG t1 ttl_col = ""; -- drop ttl attribute

删除配置的 ttl_col 字段:

nebula> ALTER TAG t1 DROP (a); -- drop ttl_col

设置 ttl_duration 为 0 或者 -1:

nebula> ALTER TAG t1 ttl_duration = 0; -- keep the ttl but the data never expires

举例

下面的例子说明,当使用 TTL 功能,而且数据过时后,查询该 tag 的数据时,过时的数据被忽略。

nebula> CREATE TAG t(id int) ttl_duration=100, ttl_col="id";
nebula> INSERT VERTEX t(id) values 102:(1584441231);

nebula> FETCH prop on t 102;
Execution succeeded (Time spent: 5.945/7.492 ms)

注意:

  1. 当某一列做为 ttl_col 值的时候,不容许 change 该列。      必须先移除 TTL 属性,再 change 该列。

  2. 对同一 tag,index 和 TTL 功能不能同时使用。即便 index 和 TTL 建立于不一样列,也不能够同时使用。

郑州哪家医院治疗不孕不育好:http://jbk.39.net/yiyuanfengcai/tsyl_zztjyy/986/

相关文章
相关标签/搜索