§ Rapid引擎(Rapid Engine)


§ Rapid引擎简述

从GreatSQL 8.0.32-25版本开始,新增Rapid存储引擎,该引擎使得GreatSQL能满足联机分析(OLAP)查询请求。

Rapid引擎采用插件(Plugin)方式嵌入GreatSQL中,可以在线动态安装或卸载。

Rapid引擎不会直接面对客户端和应用程序,用户无需修改原有的数据访问方式。它是一个无共享、内存化、混合列式存储的查询处理引擎,其设计目的是为了高性能的处理分析型查询。

§ 使用Rapid引擎加速查询

§ 启用Rapid引擎

想要使用Rapid引擎,需要安装Rapid plugin, 并且为表指定 secondary_engine 为Rapid引擎,然后将用户数据加载到Rapid引擎内存中。

首先,加载Rapid引擎这个Plugin:

greatsql> INSTALL PLUGIN Rapid SONAME 'ha_rapid.so';

greatsql> SHOW PLUGINS;
+----------------------------------+----------+--------------------+----------------------+---------+
| Name                             | Status   | Type               | Library              | License |
+----------------------------------+----------+--------------------+----------------------+---------+
| binlog                           | ACTIVE   | STORAGE ENGINE     | NULL                 | GPL     |
| mysql_native_password            | ACTIVE   | AUTHENTICATION     | NULL                 | GPL     |
...
| clone                            | ACTIVE   | CLONE              | mysql_clone.so       | GPL     |
| group_replication                | ACTIVE   | GROUP REPLICATION  | group_replication.so | GPL     |
| Rapid                            | ACTIVE   | STORAGE ENGINE     | ha_rapid.so          | GPL     |
+----------------------------------+----------+--------------------+----------------------+---------+
55 rows in set (0.00 sec)

greatsql> SHOW ENGINES;
+--------------------+---------+----------------------------------------------------------------------------+--------------+------+------------+
| Engine             | Support | Comment                                                                    | Transactions | XA   | Savepoints |
+--------------------+---------+----------------------------------------------------------------------------+--------------+------+------------+
...
| PERFORMANCE_SCHEMA | YES     | Performance Schema                                                         | NO           | NO   | NO         |
| InnoDB             | DEFAULT | Percona-XtraDB, Supports transactions, row-level locking, and foreign keys | YES          | YES  | YES        |
...
| Rapid              | YES     | Rapid storage engine                                                       | NO           | NO   | NO         |
...
+--------------------+---------+----------------------------------------------------------------------------+--------------+------+------------+
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

可以看到,Rapid引擎已经加载成功。

§ 卸载Rapid引擎

执行下面的SQL命令即可卸载Rapid引擎:

UNINSTALL PLUGIN rapid;
1

如果当前没有任何数据表加载到Rapid引擎中,则可以直接卸载成功。如果已有数据表加载到Rapid引擎中,则会有类似下面的提示:

greatsql> UNINSTALL PLUGIN rapid;
Query OK, 0 rows affected, 1 warning (0.00 sec)

greatsql> SHOW WARNINGS;
+---------+------+----------------------------------------------------+
| Level   | Code | Message                                            |
+---------+------+----------------------------------------------------+
| Warning | 1620 | Plugin is busy and will be uninstalled on shutdown |
+---------+------+----------------------------------------------------+
1 row in set (0.00 sec)
1
2
3
4
5
6
7
8
9
10

意思是当前Rapid引擎被使用中,还不能被卸载,这是需要将相关数据表从Rapid引擎中移除:

ALTER TABLE t1 SECONDARY_ENGINE = NULL;
1

等到所有数据表都从Rapid引擎中移除后,再次执行 SHOW ENGINES 就能看到已经不再支持Rapid引擎了。查看日志,也能看到类似下面的内容:

[Note] [MY-010733] [Server] Shutting down plugin 'Rapid'
1

§ 为InnoDB表加上Rapid辅助引擎

接下来对一个已存在的InnoDB引擎表,增加 SECONDARY_ENGINE 属性:

greatsql> CREATE TABLE `t1` (
  `id` int unsigned NOT NULL AUTO_INCREMENT,
  `c1` int unsigned NOT NULL DEFAULT '0',
  `c2` varchar(30) NOT NULL DEFAULT '',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB;

greatsql> ALTER TABLE t1 SECONDARY_ENGINE = rapid;

-- 查看建表DDL,发现增加了 SECONDARY_ENGINE=rapid
greatsql> SHOW CREATE TABLE t1\G
*************************** 1. row ***************************
       Table: t1
Create Table: CREATE TABLE `t1` (
  `id` int unsigned NOT NULL AUTO_INCREMENT,
  `c1` int unsigned NOT NULL DEFAULT '0',
  `c2` varchar(30) NOT NULL DEFAULT '',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci SECONDARY_ENGINE=rapid
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

从MySQL 8.0.18开始,为了支持SECONDARY ENGINE属性,新增选项 show_create_table_skip_secondary_engine 用于设置在执行 SHOW CREATE TABLE 显示表结构DDL时是否要同时显示SECONDARY ENGINE属性,其默认值是OFF,即默认要显示。此外,mysqldump中也新增相应选项 show-create-table-skip-secondary-engine,默认值是FALSE(和OFF一样),其作用相同。

接下来,执行下面SQL命令,写入一些数据:

greatsql> INSERT INTO t1 SELECT 0, RAND()*1024000, RAND()*1024000;
Query OK, 1 row affected (0.00 sec)
Records: 1  Duplicates: 0  Warnings: 0

-- 下面的SQL命令反复执行多次,构造一些数据
greatsql> INSERT INTO t1 SELECT 0, RAND()*1024000, RAND()*1024000 FROM t1;
Query OK, 1 row affected (0.00 sec)
Records: 1  Duplicates: 0  Warnings: 0

greatsql> INSERT INTO t1 SELECT 0, RAND()*1024000, RAND()*1024000 FROM t1;
Query OK, 2 rows affected (0.00 sec)
Records: 2  Duplicates: 0  Warnings: 0
...
greatsql> SELECT COUNT(*) FROM t1;
+----------+
| count(*) |
+----------+
|   131072 |
+----------+
1 row in set (0.00 sec)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

然后将用户表数据一次性全量导入到Rapid引擎中:

greatsql> ALTER TABLE t1 SECONDARY_LOAD;

-- 查看表状态,确认已加载成功,关键字:SECONDARY_LOAD="1"
greatsql> SHOW TABLE STATUS like 't1'\G
*************************** 1. row ***************************
           Name: t1
         Engine: InnoDB
        Version: 10
     Row_format: Dynamic
           Rows: 0
 Avg_row_length: 0
    Data_length: 16384
Max_data_length: 0
   Index_length: 0
      Data_free: 0
 Auto_increment: NULL
    Create_time: 2024-01-25 17:33:07
    Update_time: NULL
     Check_time: NULL
      Collation: utf8mb4_0900_ai_ci
       Checksum: NULL
 Create_options: SECONDARY_ENGINE="rapid" SECONDARY_LOAD="1"
        Comment:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

执行SQL命令 ALTER TABLE ... SECONDARY_LOAD 操作的过程是,先在辅助引擎中创建一个同名表,然后采用并行加载方式,将用户数据一次性全量导入到辅助引擎。

全量数据加载完毕后,后续的DML增量同步过程,由后台增量导入任务线程完成,详情参见后面的 3. 数据导入 相关内容。

执行SQL命令 ALTER TABLE ... SECONDARY_UNLOAD 操作会先判断辅助引擎中是否存在此表,是的话将其(从辅助引擎中)删除掉,但不会删除其(在主引擎中的)基本表。

§ 利用Rapid引擎提升查询效率

将用户数据加载到Rapid引擎后,通过下面介绍的方式,即可使用Rapid引擎提升查询效率。

选项 use_secondary_engine 是使用Rapid引擎的总控制开关,有三个可选值:[OFF, ON,FORCED](对应值是 [0, 1, 2]), 默认值是0/OFF, 可以有两种方式使用Rapid引擎:

方式一

-- 设置use_secondary_engine=ON的时候,为保证查询语句能够使用rapid,
-- 通常需要设置secondary_engine_cost_threshold = 0,或一个较小的阈值
SET use_secondary_engine = ON;
SET secondary_engine_cost_threshold = 0; 
1
2
3
4

方式二(不建议)

-- 修改会话变量,设置强制使用Rapid引擎
SET use_secondary_engine = FORCED;

-- 或执行SQL查询时指定HINT
SELECT /*+ SET_VAR(use_secondary_engine=forced) */ * FROM t1;
1
2
3
4
5

上述两种方式的差别主要在报错信息上,对于不能使用secondary engine的SQL语句(例如查询的表没有指定secondary engine,或者没有先执行SECONDARY_LOAD)的情况,如果使用方式一,那么会直接使用主引擎进行查询,可通过查看计划来判断是否使用了secondary engine; 对于方式二,则总是强制使用secondary engine,但如果无法使用时,则会报错,具体报错信息见下例:

greatsql> CREATE TABLE t2 (c1 INT PRIMARY KEY, c2 INT);
Query OK, 0 rows affected (0.08 sec)

greatsql> INSERT INTO t2 VALUES (1,1);
Query OK, 1 row affected (0.01 sec)

-- 上面建表时没指定secondary engine,查询会报错
greatsql> SELECT /*+ SET_VAR(use_secondary_engine=FORCED) */ * FROM t2;
ERROR 3889 (HY000): Secondary engine operation failed. use_secondary_engine is FORCED but query could not be executed in secondary engine.

greatsql> SELECT /*+ SET_VAR(use_secondary_engine=ON) SET_VAR(secondary_engine_cost_threshold=0) */ * FROM t2;
+----+------+
| c1 | c2   |
+----+------+
|  1 |    1 |
+----+------+
1 row in set (0.00 sec)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

接下来采用上面的方法查询表t1,体验Rapid引擎特性,查询时支持加上HINT语法:

-- 支持查询HINT用法,Extra列出现关键字:Using secondary engine RAPID
greatsql> EXPLAIN SELECT /*+ SET_VAR(use_secondary_engine=1) SET_VAR(secondary_engine_cost_threshold=0) */ * FROM t1\G
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: t1
   partitions: NULL
         type: ALL
possible_keys: NULL
          key: NULL
      key_len: NULL
          ref: NULL
         rows: 5
     filtered: 100.00
        Extra: Using secondary engine RAPID

-- 当已经设置 use_secondary_engine = 1或2 时
-- 表已经指定了Rapid辅助引擎,并且也已完成数据导入
-- 可以直接执行SELECT查询,能看到也可以直接用上Rapid引擎
greatsql> EXPLAIN SELECT * FROM t1\G
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: t1
   partitions: NULL
         type: ALL
possible_keys: NULL
          key: NULL
      key_len: NULL
          ref: NULL
         rows: 5
     filtered: 100.00
        Extra: Using secondary engine RAPID

-- 还支持设置不使用Rapid引擎查询,Extra列不再出现关键字:Using secondary engine RAPID
greatsql> EXPLAIN SELECT /*+ SET_VAR(use_secondary_engine=0) */ * FROM t1\G
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: t1
   partitions: NULL
         type: ALL
possible_keys: NULL
          key: NULL
      key_len: NULL
          ref: NULL
         rows: 5
     filtered: 100.00
        Extra: NULL
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49

选项 use_secondary_engine 的详细解释参见下方 5.1 新增系统选项

看下面一个简单对比测试结果,对一个TPC-H 1G的表执行查询:

greatsql> SELECT /*+ SET_VAR(use_secondary_engine=0) */ COUNT(*) FROM lineitem;
+----------+
| count(*) |
+----------+
|  6001215 |
+----------+
1 row in set (2.18 sec)

greatsql> SELECT /*+ SET_VAR(use_secondary_engine=1) */ COUNT(*) FROM lineitem;
+----------+
| count(*) |
+----------+
|  6001215 |
+----------+
1 row in set (0.00 sec)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

可以看到,查询速度提升效果非常明显。

还可以指定 secondary_engine_cost_threshold 选项,设置使用Rapid引擎的代价阈值:

-- 先查看执行计划的COST
greatsql> EXPLAIN FORMAT=TREE SELECT COUNT(*) FROM lineitem\G
*************************** 1. row ***************************
EXPLAIN: -> Aggregate: count(0)  (cost=1197779.30 rows=1)
    -> Table scan on lineitem in secondary engine RAPID  (cost=598889.90 rows=5988894)

-- 将 secondary_engine_cost_threshold 阈值调大到1197779
greatsql> SELECT /*+ SET_VAR(use_secondary_engine=1 SET_VAR(secondary_engine_cost_threshold=1197779) */ COUNT(*) FROM lineitem;
+----------+
| count(*) |
+----------+
|  6001215 |
+----------+
1 row in set (2.21 sec)
1
2
3
4
5
6
7
8
9
10
11
12
13
14

可以看到,虽然 lineitem 表已经加载到Rapid引擎中,但因为调大 secondary_engine_cost_threshold 阈值,实际上还是没用上。

§ Rapid引擎使用约束

在GreatSQL 8.0.32-25版本中,Rapid引擎支持的语句范围如下:

  • 表类型:InnoDB引擎的normal表。

  • SELECT stmt:不包含 SELECT INTO, SELECT locking clause 等语法。

  • PREPARE stmt:仅支持 PREPARE SELECT查询。

其余类型的SQL语法暂时还不支持。

Rapid引擎暂时不支持表分区(partition),不支持外键(foreign key)。

§ 数据导入

§ 向Rapid引擎导入数据

当对表执行 ALTER TABLE xxx SECONDARY_LOAD 操作成功后,会将InnoDB主引擎中的数据全量加载到Rapid引擎中,这个过程称为全量导入。全量导入成功后,Rapid引擎中的数据是静态的,当向主引擎表中继续插入、删除、修改数据时,并不会导入到Rapid引擎中。

利用binlog特性,可以在全量导入成功后,启动增量导入任务。增量任务会读取自全量导入成功之后的binlog数据,将binlog解析并应用到rapid引擎中,这个过程称为增量导入

不同于全量导入,增量导入会启动一个常驻的后台线程,实时读取和应用增量binlog数据。

§ 增量导入数据的限制和需求

  1. 需要设置表名大小写不敏感,即设置 lower_case_table_names = 1
  2. 需要开启GTID模式,即设置 gtid_mode = ONenforce_gtid_consistency = ON
  3. 需要采用row格式的binlog event,不支持statement格式,即设置 binlog_format = ROW。增量任务运行过程中,检测到statement的DML event,可能会报错退出。
  4. 需要关闭GIPKs特性,即设置 sql_generate_invisible_primary_key = OFF。用户表不能有 invisible primary key,如果表包含隐式不可见的主键,在全量导入过程中会报错;同时也不支持用户表中存在任何不可见列(invisible column)。
  5. 需要先对表执行过一次全量导入后,才能启动增量导入任务,否则任务启动会报错。
  6. 不支持 PARTIAL_UPDATE_ROWS_EVENT 类型的binlog,即不要设置 binlog_row_value_options = PARTIAL_JSON
  7. 不支持 CREATE TABLE SELECT 语句,增量任务运行过程中,检测到该语句产生的binlog event时可能会报错退出。
  8. 不支持XA事务,运行过程中检查到XA事务会报错退出。

§ 增量导入任务管理

新增两个系统函数用于管理增量导入任务,分别是 START_SECONDARY_ENGINE_INCREMENT_LOAD_TASK()STOP_SECONDARY_ENGINE_INCREMENT_LOAD_TASK()。顾名思义,还是很好理解的,分别对应启动和停止任务。

§ 启动增量任务

执行SQL命令 SELECT START_SECONDARY_ENGINE_INCREMENT_LOAD_TASK() 即可启动增量任务,根据函数返回信息可以确认是否任务启动成功。如果启动失败,可以从错误日志中查看具体失败的原因。

该函数包含3个参数:

  • db_name,必选项,指定增量导入任务对应的数据库名。
  • table_name,必选项,指定增量导入任务对应的数据表名。
  • gtid,可选项,指定开始增量导入任务的起始gtid_set值。默认不需要指定,任务会自动根据ALTER TABLE ... SECONDARY_LOAD 全量导入时刻的 gtid_executed 进行计算和判断。

启动增量导入任务后,每一个用户表会单独启动一个任务线程。

任务启动成功,会返回success;任务失败,会返回 start task error。具体失败的原因可以查看错误,或者查看 information_schema.SECONDARY_ENGINE_INCREMENT_LOAD_TASK 系统表。

不支持对视图(view)和 临时表(temporary table)启动增量导入任务。

-- 启动增量导入任务
greatsql> SELECT START_SECONDARY_ENGINE_INCREMENT_LOAD_TASK('tpch1g', 't1');
+------------------------------------------------------------+
| START_SECONDARY_ENGINE_INCREMENT_LOAD_TASK('tpch1g', 't1') |
+------------------------------------------------------------+
| success                                                    |
+------------------------------------------------------------+
1 row in set (0.00 sec)

-- 查看增量导入任务状态
greatsql> SELECT * FROM information_schema.SECONDARY_ENGINE_INCREMENT_LOAD_TASK\G
*************************** 1. row ***************************
           DB_NAME: tpch1g
        TABLE_NAME: t1
        START_TIME: 2024-01-26 14:54:41
        START_GTID: 4fb86f5b-b028-11ee-92b8-d08e7908bcb1:1-331
COMMITTED_GTID_SET: 4fb86f5b-b028-11ee-92b8-d08e7908bcb1:1-335
         READ_GTID: 4fb86f5b-b028-11ee-92b8-d08e7908bcb1:335
  READ_BINLOG_FILE: ./greatsql.000002
   READ_BINLOG_POS: 3589965
             DELAY: 0
            STATUS: RUNNING
          END_TIME:
              INFO:
1 row in set (0.00 sec)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

如上所示,当前的增量导入任务正在运行中,任务开始的GTID位置是:xxx:1-331,当前最新GTID是:xxx:1-335,当前增量任务进度的GTID是:xxx:335,对应的binlog file & position分别是 binlog.0000023589965

也可以在启动增量导入任务时,指定初始的GTID位置,例如执行下面的 SQL 命令:

SELECT START_SECONDARY_ENGINE_INCREMENT_LOAD_TASK('tpch1g', 't1', '4fb86f5b-b028-11ee-92b8-d08e7908bcb1:1-335');
1

增量导入任务会跳过GTID值为 1-335 区间的事务,从下一个事务开始继续增量导入。当binlog被意外清除时,默认方式(不带GTID参数)启动的增量导入任务可能会失败,这时就可以先停止增量导入任务,对该表执行一次全量导入,在全量导入完成后再次启动增量导入任务,启动任务时指定GTID参数即可。

§ 停止增量任务

执行SQL命令 SELECT STOP_SECONDARY_ENGINE_INCREMENT_LOAD_TASK() 即可停止增量任务,根据函数返回信息可以确认是否任务启动成功。如果启动失败,可以从错误日志中查看具体失败的原因。

该函数包含2个参数:

  • db_name,必选项,指定增量导入任务对应的数据库名。
  • table_name,必选项,指定增量导入任务对应的数据表名。

例如:

greatsql> SELECT STOP_SECONDARY_ENGINE_INCREMENT_LOAD_TASK('tpch1g', 't1');
+-----------------------------------------------------------+
| STOP_SECONDARY_ENGINE_INCREMENT_LOAD_TASK('tpch1g', 't1') |
+-----------------------------------------------------------+
| success                                                   |
+-----------------------------------------------------------+
1 row in set (0.65 sec)
1
2
3
4
5
6
7

§ 查看增量任务进度

执行SQL命令:SELECT READ_SECONDARY_ENGINE_TABLE_LOAD_GTID('greatsql', 't1') 即可查看任务当前导入的GTID进度。

该函数包含2个参数:

  • db_name,必选项,指定增量导入任务对应的数据库名。
  • table_name,必选项,指定增量导入任务对应的数据表名。

函数返回当前增量任务导入到的GTID位置,便于用户定位和主引擎的延迟等信息。也可以通过查看 information_schema.SECONDARY_ENGINE_INCREMENT_LOAD_TASK

例如:

+-------------------------------------------------------+
| READ_SECONDARY_ENGINE_TABLE_LOAD_GTID('tpch1g', 't1') |
+-------------------------------------------------------+
| 4fb86f5b-b028-11ee-92b8-d08e7908bcb1:1-339            |
+-------------------------------------------------------+
1 row in set (0.00 sec)

greatsql> SELECT * FROM information_schema.SECONDARY_ENGINE_INCREMENT_LOAD_TASK\G
*************************** 1. row ***************************
           DB_NAME: tpch1g
        TABLE_NAME: t1
        START_TIME: 2024-01-26 15:14:31
        START_GTID: 4fb86f5b-b028-11ee-92b8-d08e7908bcb1:1-337
COMMITTED_GTID_SET: 4fb86f5b-b028-11ee-92b8-d08e7908bcb1:1-339
         READ_GTID: 4fb86f5b-b028-11ee-92b8-d08e7908bcb1:339
  READ_BINLOG_FILE: ./binlog.000002
   READ_BINLOG_POS: 3591515
             DELAY: 0
            STATUS: RUNNING
          END_TIME:
              INFO:
1 row in set (0.01 sec)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

系统表 information_schema.SECONDARY_ENGINE_INCREMENT_LOAD_TASK 各个列解读如下:

  • DB_NAMETABLE_NAME:具体增量导入任务关联的用户表。
  • START_TIME:增量导入任务启动的时间。
  • START_GTID:增量导入任务启动时的GTID值。
  • COMMITTED_GTID_SET:增量任务执行过程中,实时导入的GTID值。
  • READ_GTID:该表增量导入任务读取到的最新GTID值。
  • READ_BINLOG_FILEREAD_BINLOG_POS:增量任务执行过程中,实时导入的BINLOG位置信息。
  • DELAY:增量任务执行过程中,实时的延迟时间,单位为秒。当增量导入任务不是在RUNNING状态,DELAY所显示延迟时长不准确,也无需再关注。
  • STATUS:增量任务状态,是否在运行。
  • END_TIME:增量导入任务如果退出,正常退出、或者异常退出,任务退出的时间点。
  • INFO:显示任务退出、或者错误的信息。

当实际导入的GTID(COMMITTED_GTID_SET)和读取到的最新GTID(READ_GTID)相等时,表明增量导入任务已跟上最新进度,没有延迟。这时还能看到 READ_BINLOG_FILEREAD_BINLOG_POS 不再变化,并且 DELAY 值为0。如下例所示,说明表 customernationpartregionsupplier 已经跟上了最新事务进度:

greatsql> SELECT TABLE_NAME, STATUS, COMMITTED_GTID_SET, READ_GTID, READ_BINLOG_FILE, READ_BINLOG_POS, DELAY FROM information_schema.SECONDARY_ENGINE_INCREMENT_LOAD_TASK;
+------------+-------------+----------------------------------------------+--------------------------------------------+------------------+-----------------+-------+
| TABLE_NAME | STATUS      | COMMITTED_GTID_SET                           | READ_GTID                                  | READ_BINLOG_FILE | READ_BINLOG_POS | DELAY |
+------------+-------------+----------------------------------------------+--------------------------------------------+------------------+-----------------+-------+
| customer   | RUNNING     | 35e7b1d9-bf0c-11ee-b7ea-d08e7908bcb1:1-42701 | 35e7b1d9-bf0c-11ee-b7ea-d08e7908bcb1:42701 | ./binlog.000003  |       171177719 |     0 |
| lineitem   | RUNNING     | 35e7b1d9-bf0c-11ee-b7ea-d08e7908bcb1:1-42427 | 35e7b1d9-bf0c-11ee-b7ea-d08e7908bcb1:42428 | ./binlog.000001  |      1016454504 |  5528 |
| nation     | RUNNING     | 35e7b1d9-bf0c-11ee-b7ea-d08e7908bcb1:1-42701 | 35e7b1d9-bf0c-11ee-b7ea-d08e7908bcb1:42701 | ./binlog.000003  |       171177719 |     0 |
| orders     | RUNNING     | 35e7b1d9-bf0c-11ee-b7ea-d08e7908bcb1:1-42429 | 35e7b1d9-bf0c-11ee-b7ea-d08e7908bcb1:42430 | ./binlog.000002  |        27569846 |  5466 |
| part       | RUNNING     | 35e7b1d9-bf0c-11ee-b7ea-d08e7908bcb1:1-42701 | 35e7b1d9-bf0c-11ee-b7ea-d08e7908bcb1:42701 | ./binlog.000003  |       171177719 |     0 |
| partsupp   | RUNNING     | 35e7b1d9-bf0c-11ee-b7ea-d08e7908bcb1:1-42431 | 35e7b1d9-bf0c-11ee-b7ea-d08e7908bcb1:42432 | ./binlog.000002  |       231344911 |  5454 |
| region     | RUNNING     | 35e7b1d9-bf0c-11ee-b7ea-d08e7908bcb1:1-42701 | 35e7b1d9-bf0c-11ee-b7ea-d08e7908bcb1:42701 | ./binlog.000003  |       171177719 |     0 |
| supplier   | RUNNING     | 35e7b1d9-bf0c-11ee-b7ea-d08e7908bcb1:1-42701 | 35e7b1d9-bf0c-11ee-b7ea-d08e7908bcb1:42701 | ./binlog.000003  |       171177719 |     0 |
+------------+-------------+----------------------------------------------+--------------------------------------------+------------------+-----------------+-------+
8 rows in set (0.00 sec)
1
2
3
4
5
6
7
8
9
10
11
12
13
14

当增量导入任务停止后,查询状态结果如下所示:

greatsql> SELECT * FROM information_schema.SECONDARY_ENGINE_INCREMENT_LOAD_TASK\G
*************************** 1. row ***************************
           DB_NAME: tpch1g
        TABLE_NAME: t1
        START_TIME: 2024-01-26 15:14:31
        START_GTID: 4fb86f5b-b028-11ee-92b8-d08e7908bcb1:1-337
COMMITTED_GTID_SET: 4fb86f5b-b028-11ee-92b8-d08e7908bcb1:1-339
         READ_GTID: 4fb86f5b-b028-11ee-92b8-d08e7908bcb1:339
  READ_BINLOG_FILE: ./binlog.000002
   READ_BINLOG_POS: 3591515
             DELAY: 6
            STATUS: NOT RUNNING
          END_TIME: 2024-01-26 15:35:18
              INFO: NORMAL EXIT
1 row in set (0.00 sec)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

§ 增量任务线程

  1. 每一个用户表的增量导入任务对应一个后台线程,该线程只负责处理将该表的增量数据导入到Rapid。所以如果加载的Rapid表很多,可能会消耗较多线程资源。
  2. 增量任务执行过程中,根据之前的测试,对于UPDATE/DELETE 语句在Rapid引擎中执行较慢,可能导致增量导入任务线程延迟加大。

§ 辅助查询概述

由于用户表的主引擎可能产生实时变更的新数据,因此对于辅助引擎的查询,即使开启了增量导入任务,相对主引擎,Rapid引擎的数据也还是可能存在延迟。针对数据延迟问题,新增了如下5个 SESSION/GLOBAL 选项,标记在何种条件下仍旧通过Rapid引擎进行数据读操作。

选项名 类型 默认值 最小值 最大值 说明
secondary_engine_read_delay_time_threshold ULONG 60 0 ULONG_MAX 允许最大的读延迟时间
secondary_engine_read_delay_gtid_threshold ULONG 100 0 ULONG_MAX 允许最大的读延迟事务数
secondary_engine_read_delay_wait_timeout ULONG 60 0 ULONG_MAX 读延迟时最大等待超时时间
secondary_engine_read_delay_wait_mode ENUM WAIT_FOR_TRX [WAIT_FOR_TRX, WAIT_FOR_DB] 读延迟时查询等待模式
secondary_engine_read_delay_level ENUM TABLE_START_INC_TASK [ALL_TABLES, TABLE_START_INC_TASK] 读延迟级别

几个选项分别解释如下:

  • secondary_engine_read_delay_time_threshold:指定辅助引擎查询时,数据的最大允许延时时间,时间单位为秒。默认值为 60,可选范围为 [0 ~ ULONG_MAX]。如果选项值为0,表示不允许延迟,即如果Rapid擎相对主引擎的数据有延迟,都不允许查询。如果设置不为0,则实际延迟小于选项值,可以查询;否则不允许查询。
  • secondary_engine_read_delay_gtid_threshold:执行辅助引擎查询时,允许延迟的最大事务数。默认值为 100,即允许100个事务内的延迟;可选范围为 [0 ~ ULONG_MAX]。如果选项值为0,表示不允许延迟,即如果辅助引擎相对主引擎的数据有延迟,都不允许查询。如果设置不为0,则实际延迟小于选项值,可以查询;否则不允许查询。
  • secondary_engine_read_delay_wait_timeout:指定辅助引擎查询时,如果数据出现延迟,不管是时间延迟,还是基于GTID的事务延迟,此时是不允许查询的。本选项用于设置允许当出现这种状况时,指定一个查询超时时间,在触发超时之前,可以持续等待并检测延迟情况,如果延迟降低到允许范围内,则可以继续查询;否则,如果触发超时,则最后报错。时间单位为秒,默认值为 60,可选范围为 [0 ~ ULONG_MAX]。如果设置为0,则如果延迟超限,直接报错。如果设置不为0,则以实际的超时时间为准。
  • secondary_engine_read_delay_wait_mode:本选项是对secondary_engine_read_delay_wait_timeout的补充,本选项指定了等待超时的模式,有两个可选值 [WAIT_FOR_DB, WAIT_FOR_TRX],默认为 WAIT_FOR_TRX。如果设置为WAIT_FOR_DB,则在 secondary_engine_read_delay_wait_timeout 设定的超时范围内,每次都以主引擎最新状态进行对比;如果设置为 WAIT_FOR_TRX,则在secondary_engine_read_delay_wait_timeout 设定的超时范围内,每次都以查询语句/事务开启时的状态进行对比。所以,如果采用WAIT_FOR_DB 模式,并将 secondary_engine_read_delay_wait_timeout 设置为最大值,可能导致查询永远满足不了延迟条件的可能。
  • secondary_engine_read_delay_level:指定辅助引擎查询时,支持延迟查询的表的严格级别。支持两个可选值 [ALL_TABLES, TABLE_START_INC_TASK],默认为TABLE_START_INC_TASK。当设置为 ALL_TABLES 时,不管该表是否开启了增量导入任务,都需要检查延迟。如果设置为 TABLE_START_INC_TASK,则如果表没有开启增量导入任务、或者增量导入任务因任何原因停止,对该表查询时,不检查和主引擎的延迟。

§ 解读Rapid引擎

§ 体系结构

Rapid引擎整体架构如下图所示 GreatSQL Rapid引擎体系结构图

  • Rapid引擎的核心代码是采用C++11开发,该引擎没有任何其他的依赖。
  • Rapid引擎适用于OLAP场景,它采用向量化计算技术,充分利用CPU SIMD技术。
  • Rapid引擎内部采用DataBlocks存储结构,这是一种兼顾OLTP和OLAP的压缩存储结构。其数据存储的基本格式:RowGroup based Storage。存储引擎将一个表的数据按行划分为多个RowGroup的组合,每个RowGroup最大存储122880行,内部数据按列进行存储。
  • Rapid内部是一个基于矢量化推送的模型(vectorized push-based model),在执行过程中,向量(vector)会在各个操作符之间流转,而不是一个个元组(tuple),采用了 Morsel驱动并行实现方式,将一个执行计划切分成多个管道(pipeline),每个管道采用 push-based的方式进行数据传递和调用。

启用Rapid引擎后,会在数据库主目录datadir中产生一些新文件/目录,主要有:

  • duckdb.data,Rapid引擎数据文件,存储所有Rapid引擎表用户数据,类似InnoDB系统表空间文件ibdata*,已分配的磁盘空间可以重复使用,但在用户数据删除后不能回收归还操作系统。如果想要让Rapid引擎数据文件释放占用的磁盘空间,需要先卸载Rapid,而后即可删除相关文件,再次启用Rapid引擎即可。请参考 2.1 启用Rapid引擎2.2 卸载Rapid引擎

  • duckdb.data.wal,Rapid引擎的预写日志,在Rapid引擎运行过程中,对其的所有修改操作在提交之前,都会预先写入日志,以保证数据库系统的原子性和持久性。

  • duckdb.data.tmp,Rapid引擎存放临时文件的目录。Rapid引擎运行时,在执行大查询请求或加载大量数据时,如果内存不足,则需要将运行过程中产生的数据先保存在临时文件中。

用户数据表加载到Rapid引擎中的过程简述如下:

  1. 用户发起 ALTER TABLE ... SECONDARY_LOAD 操作;

  2. 读取表数据,以Rapid引擎的数据结构写入到WAL预写日志文件中;

  3. 如果表数据量特别大,无法完全装载到rapid_memory_limit设定的内存中,则会产生临时文件,临时文件存储在rapid_temp_directory目录下;

  4. 表数据全部读取完成后,再以压缩方式回写到Rapid引擎数据文件duckdb.data中,在这个过程中逐步清理临时文件,相应的内存消耗也在逐步降低;

  5. 全部写入完成后,自动清理WAL日志文件和临时文件。

当加载到Rapid引擎的数据量特别大时,需要用到大量内存块,这时有可能发生发生报错导致加载失败。这时可以尝试调大内核参数vm.max_map_count。它决定了一个进程可以拥有的最大内存映射区域数。内存映射区域是指内存映射文件、匿名内存映射等。这个参数对于一些可能要用到大量内存的应用程序(尤其是数据库服务进程)特别重要,因为它们在运行时会创建大量的内存映射区域。

内核参数 vm.max_map_count 的默认值通常是较小的数值,例如 65530。这个值对于要加载大量数据到Rapid引擎中的场景可能就不够用了,需要适当调大。编辑 /etc/sysctl.conf 系统文件,增加下面一行内容:

vm.max_map_count = 6553000
1

然后执行 sysctl -p 使其生效:

$ sysctl -p
vm.max_map_count = 6553000

# 并再次确认生效
$ sysctl -a | grep vm.max_map_count
vm.max_map_count = 6553000
1
2
3
4
5
6

§ 支持的数据类型

Rapid引擎支持以下数据类型

大类 数据类型 备注
数字型 BOOL, BOOLEAN 布尔类型。存储为TINYINT(1)
0为false,非0为true
TINYINT[(M)] [UNSIGNED] [ZEROFILL] 有符号,无符号,1字节
SMALLINT[(M)] [UNSIGNED] [ZEROFILL] 有符号,无符号,2字节
MEDIUMINT[(M)] [UNSIGNED] [ZEROFILL] 有符号,无符号,3字节
INT[(M)] [UNSIGNED] [ZEROFILL]
INTEGER[(M)] [UNSIGNED] [ZEROFILL]
有符号,无符号,4字节
BIGINT[(M)] [UNSIGNED] [ZEROFILL] 有符号,无符号,8字节
FLOAT[(M,D)] [UNSIGNED] [ZEROFILL] 单精度浮点数
FLOAT(p) [UNSIGNED] [ZEROFILL] p在[0, 24]中,是FLOAT
p在[25, 53]中,是DOUBLE
DOUBLE[(M,D)] [UNSIGNED] [ZEROFILL]
DOUBLE PRECISION[(M,D)] [UNSIGNED] [ZEROFILL]
REAL[(M,D)] [UNSIGNED] [ZEROFILL]
双精度浮点数,若 REAL_AS_FLOAT 模式开启,REAL则变成FLOAT的别名
DECIMAL[(M[,D])] [UNSIGNED] [ZEROFILL]
DEC[(M[,D])] [UNSIGNED] [ZEROFILL]
NUMERIC[(M[,D])] [UNSIGNED] [ZEROFILL]
FIXED[(M[,D])] [UNSIGNED] [ZEROFILL]
固定宽度与精度的数
+-*/的运算结果按精度65算
日期时间型 DATE 日期
TIME[(fsp)] 时间;fsp可取[0, 6]
DATETIME[(fsp)] 日期+时间;fsp可取[0, 6]
TIMESTAMP[(fsp)] 时间戳
存:当前时区转成UTC时区去存储
取:UTC转成当前时区取出并显示
YEAR[(4)]
字符型 CHAR(n) 定长字符串
VARCHAR(n) 变长字符串

§ 运维管理

Rapid引擎相关的选项设置主要包括系统选项和插件选项两类:

  • 系统选项,开启使用Rapid引擎,设置Rapid引擎并行加载参数。
  • 插件选项,针对Rapid引擎内部的选项设置。

§ 新增系统选项

System Variable Name Variable Scope Dynamic Variable Permitted Values Type Default Description
use_secondary_engine Session YES [ON/OFF/FORCED] Boolean OFF 是否使用secondary engine开关
secondary_engine_cost_threshold Global, Session YES [0, DBL_MAX] DOUBLE 100000.000000 使用secondary engine执行查询的代价阈值
secondary_engine_parallel_load_workers Session YES [1, 32] UINT 4 secondary engine全量加载并行写线程数目
secondary_engine_read_delay_gtid_threshold Global, Session YES [0, ULONG_MAX] ULONG 100 执行辅助引擎查询时,允许延迟的最大事务数
secondary_engine_read_delay_level Global, Session YES [ALL_TABLES, TABLE_START_INC_TASK] ENUM TABLE_START_INC_TASK 指定辅助引擎查询时,支持延迟查询的表的严格级别
secondary_engine_read_delay_time_threshold Global, Session YES [0, ULONG_MAX] ULONG 60 指定辅助引擎查询时,数据的最大允许延时时间
secondary_engine_read_delay_wait_mode Global, Session YES [WAIT_FOR_TRX, WAIT_FOR_DB] ENUM WAIT_FOR_TRX 指定辅助引擎查询时,读延迟时查询等待模式
secondary_engine_read_delay_wait_timeout Global, Session YES [0, ULONG_MAX] ULONG 60 指定辅助引擎查询时,读延迟时最大等待超时时间

§ 新增插件选项

新增以下插件选项,用于设定Rapid引擎相关选项。

System Variable Name Variable Scope Dynamic Variable Permitted Values Type Default Description
rapid_memory_limit Global YES [2^26, 2^39] LONGLONG 1GB(2^30) Rapid引擎运行过程中可使用的内存,默认值1G
rapid_worker_threads Global YES [1, LONG_MAX] LONG 4 Rapid引擎运行过程中可使用的线程数
rapid_hash_table_memory_limit Global YES [10, 80] LONG 10 Rapid引擎运行过程中hash table最大可使用memory_limit的比例
rapid_temp_directory Global NO String "duckdb.data.tmp" Rapid引擎存放临时文件的目录。当启用Rapid引擎后,不支持修改;启用之前,可修改
rapid_checkpoint_threshold Global YES [0, 2^39] LONGLONG 16MB(2^24) 触发自动checkpoint操作的WAL大小阈值。WAL文件是Rapid引擎的预写日志,在Rapid引擎运行过程中,对其的所有修改操作在提交之前,都会预先写入日志,以保证数据库系统的原子性和持久性

§ 新增状态变量

新增状态变量 Secondary_engine_execution_count 用于统计辅助引擎表上执行查询的次数。例如:

-- 查看全局状态变量
greatsql> SHOW GLOBAL STATUS LIKE 'Secondary_engine_execution_count';
+----------------------------------+-------+
| Variable_name                    | Value |
+----------------------------------+-------+
| Secondary_engine_execution_count | 37    |
+----------------------------------+-------+

-- 查看session级状态变量
greatsql> SHOW STATUS LIKE 'Secondary_engine_execution_count';
+----------------------------------+-------+
| Variable_name                    | Value |
+----------------------------------+-------+
| Secondary_engine_execution_count | 0     |
+----------------------------------+-------+

-- 查看执行计划,确认可以走Rapid引擎
greatsql> EXPLAIN SELECT * FROM t1;
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+------------------------------+
| id | select_type | table | partitions | type | possible_keys | key  | key_len | ref  | rows | filtered | Extra                        |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+------------------------------+
|  1 | SIMPLE      | t1    | NULL       | ALL  | NULL          | NULL | NULL    | NULL |   25 |   100.00 | Using secondary engine RAPID |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+------------------------------+
1 row in set, 1 warning (0.00 sec)

-- 执行一次查询
greatsql> SELECT * FROM t1;

-- 再次查看全局/session级状态变量,发现分别都增加了1
greatsql> SHOW GLOBAL STATUS LIKE 'Secondary_engine_execution_count';
+----------------------------------+-------+
| Variable_name                    | Value |
+----------------------------------+-------+
| Secondary_engine_execution_count | 38    |
+----------------------------------+-------+

greatsql> SHOW STATUS LIKE 'Secondary_engine_execution_count';
+----------------------------------+-------+
| Variable_name                    | Value |
+----------------------------------+-------+
| Secondary_engine_execution_count | 1     |
+----------------------------------+-------+
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42

§ 部分内存参数的使用说明

在GreatSQL实例启动加载Rapid引擎时,会读取Rapid引擎元数据,扫描到已经加载过的表,然后把这些表数据再次加载到内存中,实例启动完成后,无需再次手动加载,就正常使用Rapid引擎来提升查询效率了。

使用Rapid引擎时,倾向于将数据全部加载到内存来提高并行计算性能。

因此执行部分SQL查询时可能遇到报告内存不足的错误。如果出现这种情况,可以调整如下几个选项,尝试解决问题。

  • 增加 rapid_memory_limit,在任何时候,增加Rapid引擎可使用的内存都是首选方案。

  • 如果SQL查询的执行计划有多层hash join,可尝试适当调低 rapid_hash_table_memory_limit

  • 如果SQL查询的执行计划比较复杂(如大数据量+多重hash join+多重agg),可尝试适当调低 rapid_worker_threads

选项 rapid_hash_table_memory_limit 是针对单个hash join算子的。因此如果SQL查询请求包含3重hash join,则保守估计这个选项最大只能设置为30,也就是hash join最大可消耗 rapid_memory_limit * 30% 内存资源。考虑到同时还有其他算子的对内存资源的占用,这个选项可能还要再适当调小一点。如果hash join的内存需求量超过了这个阈值,那么会改走磁盘完成查询,分批进行hash join,这时SQL查询效率就会降低很多。

另外,对于 rapid_memory_limit 这部分内存是随着SQL查询请求的执行向操作系统申请的,但它不会在SQL查询请求结束后自动释放归还给操作系统。若有需要,可手动执行 SET GLOBAL rapid_memory_limit = N 重新设置(调低)Rapid引擎的内存资源分配。

当数据量较大,但 rapid_memory_limit 设置较小时,可能导致SQL查询请求无法完成,并且报告类似下面的错误:

greatsql> SELECT ...
ERROR 3877 (HY000): Out of Memory Error: failed to pin block of size 262KB (234.2MB/134.2MB used)
1
2

在该SQL查询请求执行期间,还会产生较大临时文件,例如:

$ ls -lh duckdb.data.tmp/

...
-rw-r-----. 1 mysql mysql 277M Jan 30 02:38 duckdb_temp_storage-0.tmp
1
2
3
4

或者,当有个表需要一次性全量导入加载到Rapid引擎中时,也可能会产生较大的临时文件,例如:

-- 本例中,lineitem表大小1.4GB,有600万行数据
ALTER TABLE lineitem SECONDARY_LOAD;
1
2

在另一个终端观察临时文件大小:

$ ls -lh duckdb.data.tmp/

...
-rw-r-----. 1 mysql mysql 860M Jan 30 02:47 duckdb_temp_storage-0.tmp
1
2
3
4

这种情况下,需要适当调大 rapid_memory_limit 的值。

当Rapid引擎的内存(rapid_memory_limit)可以容纳全部数据时,则不会启用临时文件;而当不够时,会启用临时文件,将部分数据存储在磁盘,并生成对应的tmp文件,临时文件所在目录由选项 rapid_temp_directory 定义,当Rapid引擎开始生成临时文件后,该选项值不可再被更改,否则会导致系统运行报错。

针对不同TPC-H应用数据量级,可能较为合适的建议配置参考如下。注意:这个不是最优参考设置,而是一个适合对应数据量的推荐值,用户可以从这个列表入手,微调找到自己合适的值。当然,理论上这些值都是越大越好的。

TPC-H仓库大小 rapid_memory_limit参考值 rapid_hash_table_memory_limit参考值 rapid_worker_threads参考值
10GB 1GB 30 8
100GB 30GB 30 16
1TB 300GB 30 64

需要再补充的是,Rapid引擎内部还会额外使用一些小块内存,这部分内存不受 rapid_memory_limit 选项控制,这些小内存块的消耗与 rapid_worker_threads 以及并行执行SQL查询请求的数量正相关。因此Rapid引擎实际使用的内存通常会比 rapid_memory_limit 大一点。

§ 统计信息

用户数据表的统计信息和索引统计信息,暂不支持Rapid引擎视图查看,只能查看主引擎相关视图:

-- 查看表统计信息
SHOW TABLE STATUS LIKE 't1';

-- 查看索引统计信息
SHOW INDEX FROM t1;
1
2
3
4
5

§ 执行计划

查看查询是否使用了Rapid引擎,可通过 EXPLAIN SELECT 或者 EXPLAIN FORMAT=TREE 显示是否有Rapid关键字。

目前,EXPLAIN FORMAT=TREE 暂不支持显示Rapid引擎具体执行计划, 只可通过该方式来判断语句是否使用了Rapid引擎。

greatsql> EXPLAIN SELECT * FROM t1;
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+------------------------------+
| id | select_type | table | partitions | type | possible_keys | key  | key_len | ref  | rows | filtered | Extra                        |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+------------------------------+
|  1 | SIMPLE      | t1    | NULL       | ALL  | NULL          | NULL | NULL    | NULL |    2 |   100.00 | Using secondary engine RAPID |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+------------------------------+
1 row in set, 1 warning (0.00 sec)

greatsql> EXPLAIN FORMAT=TREE  SELECT * FROM t1;
+--------------------------------------------------------------------+
| EXPLAIN                                                            |
+--------------------------------------------------------------------+
| -> Table scan on t1 in secondary engine RAPID  (cost=0.70 rows=2)
 |
+--------------------------------------------------------------------+
1 row in set, 1 warning (0.00 sec)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

目前,Rapid引擎不支持 EXPLAIN ANALYZE 用法。

§ 元数据

可以执行下面的SQL,查询当前有哪些表使用了Rapid引擎:

greatsql> SELECT * FROM information_schema.TABLES WHERE TABLE_SCHEMA = 'tpch100' AND CREATE_OPTIONS LIKE '%Rapid%';
+---------------+----------------+------------+------------+--------+---------+------------+------------+----------------+-------------+-----------------+--------------+-----------+----------------+---------------------+-------------+------------+--------------------+----------+---------------------------------------------+---------------+
| TABLE_CATALOG | TABLE_SCHEMA   | TABLE_NAME | TABLE_TYPE | ENGINE | VERSION | ROW_FORMAT | TABLE_ROWS | AVG_ROW_LENGTH | DATA_LENGTH | MAX_DATA_LENGTH | INDEX_LENGTH | DATA_FREE | AUTO_INCREMENT | CREATE_TIME         | UPDATE_TIME | CHECK_TIME | TABLE_COLLATION    | CHECKSUM | CREATE_OPTIONS                              | TABLE_COMMENT |
+---------------+----------------+------------+------------+--------+---------+------------+------------+----------------+-------------+-----------------+--------------+-----------+----------------+---------------------+-------------+------------+--------------------+----------+---------------------------------------------+---------------+
| def           | tpch100g_rapid | customer   | BASE TABLE | InnoDB |      10 | Dynamic    |   14854987 |            210 |  3124756480 |               0 |    330219520 |         0 |           NULL | 2024-01-30 21:23:08 | NULL        | NULL       | utf8mb4_0900_ai_ci |     NULL | SECONDARY_ENGINE="rapid" SECONDARY_LOAD="1" |               |
| def           | tpch100g_rapid | lineitem   | BASE TABLE | InnoDB |      10 | Dynamic    |  582868392 |            168 | 98148810752 |               0 |  30295408640 |         0 |           NULL | 2024-01-30 21:23:08 | NULL        | NULL       | utf8mb4_0900_ai_ci |     NULL | SECONDARY_ENGINE="rapid" SECONDARY_LOAD="1" |               |
| def           | tpch100g_rapid | nation     | BASE TABLE | InnoDB |      10 | Dynamic    |         25 |            655 |       16384 |               0 |        16384 |         0 |           NULL | 2024-01-30 21:23:08 | NULL        | NULL       | utf8mb4_0900_ai_ci |     NULL | SECONDARY_ENGINE="rapid" SECONDARY_LOAD="1" |               |
| def           | tpch100g_rapid | orders     | BASE TABLE | InnoDB |      10 | Dynamic    |  148492582 |            146 | 21699231744 |               0 |   3329179648 |   6291456 |           NULL | 2024-01-30 21:23:08 | NULL        | NULL       | utf8mb4_0900_ai_ci |     NULL | SECONDARY_ENGINE="rapid" SECONDARY_LOAD="1" |               |
| def           | tpch100g_rapid | part       | BASE TABLE | InnoDB |      10 | Dynamic    |   19943155 |            176 |  3525312512 |               0 |            0 |         0 |           NULL | 2024-01-30 21:23:08 | NULL        | NULL       | utf8mb4_0900_ai_ci |     NULL | SECONDARY_ENGINE="rapid" SECONDARY_LOAD="1" |               |
| def           | tpch100g_rapid | partsupp   | BASE TABLE | InnoDB |      10 | Dynamic    |   79832625 |            226 | 18117296128 |               0 |   3886923776 |         0 |           NULL | 2024-01-30 21:23:08 | NULL        | NULL       | utf8mb4_0900_ai_ci |     NULL | SECONDARY_ENGINE="rapid" SECONDARY_LOAD="1" |               |
| def           | tpch100g_rapid | region     | BASE TABLE | InnoDB |      10 | Dynamic    |          5 |           3276 |       16384 |               0 |            0 |         0 |           NULL | 2024-01-30 21:23:08 | NULL        | NULL       | utf8mb4_0900_ai_ci |     NULL | SECONDARY_ENGINE="rapid" SECONDARY_LOAD="1" |               |
| def           | tpch100g_rapid | supplier   | BASE TABLE | InnoDB |      10 | Dynamic    |     989416 |            186 |   184369152 |               0 |     20496384 |         0 |           NULL | 2024-01-30 21:23:08 | NULL        | NULL       | utf8mb4_0900_ai_ci |     NULL | SECONDARY_ENGINE="rapid" SECONDARY_LOAD="1" |               |
+---------------+----------------+------------+------------+--------+---------+------------+------------+----------------+-------------+-----------------+--------------+-----------+----------------+---------------------+-------------+------------+--------------------+----------+---------------------------------------------+---------------+
8 rows in set (0.01 sec)
1
2
3
4
5
6
7
8
9
10
11
12
13
14

执行下面的SQL,可以查询当前增量数据导入状态:

greatsql> SELECT * FROM information_schema.SECONDARY_ENGINE_INCREMENT_LOAD_TASK\G
*************************** 1. row ***************************
           DB_NAME: tpch1g
        TABLE_NAME: t1
        START_TIME: 2024-01-26 15:14:31
        START_GTID: 4fb86f5b-b028-11ee-92b8-d08e7908bcb1:1-337
COMMITTED_GTID_SET: 4fb86f5b-b028-11ee-92b8-d08e7908bcb1:1-339
         READ_GTID: 4fb86f5b-b028-11ee-92b8-d08e7908bcb1:339
  READ_BINLOG_FILE: ./binlog.000002
   READ_BINLOG_POS: 3591515
             DELAY: 6
            STATUS: NOT RUNNING
          END_TIME: 2024-01-26 15:35:18
              INFO: NORMAL EXIT
1 row in set (0.00 sec)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

§ 性能表现参考

§ TPC-H测试表现

GreatSQL Rapid引擎性能表现优异,在32C64G测试机环境下,TPC-H 100G测试中22条SQL总耗时仅需不到80秒。下面是和其他类似产品的对比数据,仅供参考(测试时间:2024.1.31): tpch100g-rapid-vs-stonedb-starrocks

§ 数据压缩比

下面是几个不同TPC-H数据量级的压缩比数据:

TPC-H仓库大小 InnoDB引擎数据文件大小 Rapid引擎数据文件大小 压缩比
TPC-H 1GB 2003026076 276574208 7.24
TPC-H 100GB 184570593436 28728373248 6.42
TPC-H 500GB 1167795142848 146723045376 7.96

更多关于 Rapid 引擎 TPC-H 测试报告详情请参考:GreatSQL TPC-H 性能测试报告

§ 构建专属AP查询服务器

可以利用主从复制或MGR组复制方式构建一个读写分离场景,主节点上仍采用InnoDB引擎,选择一个专属从节点响应AP查询请求,该从节点上的数据表加上Rapid辅助引擎,这样就可以在从节点利用Rapid引擎响应AP查询请求了。

但也要注意,此时如果主节点上执行了Rapid引擎不支持的SQL命令,例如ADD COLUMNTRUNCATE等操作,会导致从节点复制报错。此时需要人为介入处理,先将该表移除Rapid辅助引擎,重启复制线程,使得复制线程正常工作。待到复制线程应用完事务后,再将该表加上Rapid引擎,继续响应AP查询请求。

我们还在持续优化Rapid引擎,以支持更多特性和应用场景。

§ 注意事项

  • 当前Rapid引擎的动态库文件仅支持运行在X86/ARM架构下的CentOS 7/8系统,或对应glibc版本分别是2.17和2.28,其他环境暂不支持。
  • 用户数据表主引擎只能是InnoDB引擎,不支持MyISAM等其他引擎。
  • 当前Rapid引擎还处于Alpha版本阶段,尚未达到GA(General Availability)阶段,重要线上生产环境中使用需谨慎。
  • 数据库实例重启后,查询个别Rapid引擎表可能会提示无法使用Rapid引擎加速,这时可以尝试执行 ALTER TABLE ... SECONDARY_LOAD 将该表再次加载到Rapid引擎中,实际上无需重新加载一次,速度非常快,之后就可以使用Rapid引擎了。
  • 由于底层存储结构的差异,用户从InnoDB主引擎和Rapid辅助引擎分别读取数据时,如果不加相同的排序规则,则读取到的数据顺序可能不一致。
  • 运行 OLAP 类查询通常需要更多内存,运行结束后内存可能无法立即回收,导致再次执行 OLAP 查询时会报告类似下面的错误,这种情况下可以耐心再等一段时间后再执行查询,应该就可以了。如果还是会报错,可以尝试适当加大 rapid_memory_limit 选项值。
ERROR 3877 (HY000): Out of Memory Error: Failed to allocate block of 8192 bytes
1
  • 不支持在同一个SQL查询中,混合使用 InnoDB 和 Rapid 引擎。也就是说,当一个 Rapid 引擎表和一个 InnoDB 引擎表之间进行 JOIN 关联查询时,是无法利用 Rapid 引擎来提升查询效率,只能两个表都走 InnoDB 引擎的执行计划。如下例所示(t1 是 InnoDB 引擎表,t3 是 Rapid 引擎表):
greatsql> SELECT TABLE_SCHEMA, TABLE_NAME, CREATE_OPTIONS FROM information_schema.tables WHERE TABLE_SCHEMA = 'test';
+--------------+------------+---------------------------------------------+
| TABLE_SCHEMA | TABLE_NAME | CREATE_OPTIONS                              |
+--------------+------------+---------------------------------------------+
| test         | t1         | SECONDARY_ENGINE="rapid" SECONDARY_LOAD="1" |
| test         | t3         | SECONDARY_ENGINE="rapid" SECONDARY_LOAD="1" |
+--------------+------------+---------------------------------------------+

greatsql> EXPLAIN SELECT /*+ SET_VAR(use_secondary_engine = ON) */ * FROM t1, t3 WHERE t1.b = t3.b;
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+--------------------------------------------+
| id | select_type | table | partitions | type | possible_keys | key  | key_len | ref  | rows | filtered | Extra                                      |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+--------------------------------------------+
|  1 | SIMPLE      | t3    | NULL       | ALL  | NULL          | NULL | NULL    | NULL |    1 |   100.00 | NULL                                       |
|  1 | SIMPLE      | t1    | NULL       | ALL  | NULL          | NULL | NULL    | NULL |    2 |    50.00 | Using where; Using join buffer (hash join) |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+--------------------------------------------+
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

扫码关注微信公众号

greatsql-wx