OceanBase学习之路14|体验并行导入 & 数据压缩

本文介绍了并行导入和数据压缩相关的使用及说明。

并行导入

除了分析查询,Operational OLAP 中还有很重要的一个部分,那就是大量数据的并行导入,也就是数据批处理能力。OceanBase 数据库的并行执行框架能够将 DML 语句也通过并发的方式进行执行(Parallel DML),对于多节点的数据库,实现多机并发写入,并且保证大事务的一致性。结合异步转储机制,还能在很大程度上优化 LSM tree 存储引擎在内存紧张的情况下对大事务的支持。

我们通过这样一个例子来体验 PDML:仍然以 TPC-H 的  lineitem 表为基础,创建一张相同表结构的空表  lineitem2。然后以  INSERT INTO ...SELECT 的方式,用一条 SQL 语句将  lineitem 的全部 600 万行数据插入到新表  lineitem2 中。下面我们分别用关闭和开启 PDML 的方式执行,观察其效果和区别。

首先,复制  lineitem 的表结构,创建  lineitem2。注意,在 OceanBase 数据库中我们使用分区表进行数据扩展,此处的例子中我们使用 16 个分区,那么对应的  lineitem2 也应完全相同:

obclient> SHOW CREATE TABLE lineitem\G;
*************************** 1. row ***************************
       Table: lineitem
Create Table: CREATE TABLE `lineitem` (
  `l_orderkey` bigint(20) NOT NULL,
  `l_partkey` bigint(20) NOT NULL,
  `l_suppkey` bigint(20) NOT NULL,
  `l_linenumber` bigint(20) NOT NULL,
  `l_quantity` bigint(20) NOT NULL,
  `l_extendedprice` bigint(20) NOT NULL,
  `l_discount` bigint(20) NOT NULL,
  `l_tax` bigint(20) NOT NULL,
  `l_returnflag` char(1) DEFAULT NULL,
  `l_linestatus` char(1) DEFAULT NULL,
  `l_shipdate` date NOT NULL,
  `l_commitdate` date DEFAULT NULL,
  `l_receiptdate` date DEFAULT NULL,
  `l_shipinstruct` char(25) DEFAULT NULL,
  `l_shipmode` char(10) DEFAULT NULL,
  `l_comment` varchar(44) DEFAULT NULL,
  PRIMARY KEY (`l_orderkey`, `l_linenumber`),
  KEY `I_L_ORDERKEY` (`l_orderkey`) BLOCK_SIZE 16384 LOCAL,
  KEY `I_L_SHIPDATE` (`l_shipdate`) BLOCK_SIZE 16384 LOCAL
) DEFAULT CHARSET = utf8mb4 ROW_FORMAT = COMPACT COMPRESSION = 'zstd_1.3.8' REPLICA_NUM = 1 BLOCK_SIZE = 16384 USE_BLOOM_FILTER = FALSE TABLET_SIZE = 134217728 PCTFREE = 0 TABLEGROUP = 'x_tpch_tg_lineitem_order_group'
 partition by key(l_orderkey)
  (partition p0,
  partition p1,
  partition p2,
  partition p3,
  partition p4,
  partition p5,
  partition p6,
  partition p7,
  partition p8,
  partition p9,
  partition p10,
  partition p11,
  partition p12,
  partition p13,
  partition p14,
  partition p15)
1 row in set

默认方式执行,不开启 PDML

创建好  lineitem2 后,我们先以默认配置不开启并行的方式插入, 因为这是一个 600 万行的大事务,我们需要将 OceanBase 数据库默认的事务超时时间调整到更大的值(单位为 μs):

SET ob_query_timeout = 1000000000;  
SET ob_trx_timeout = 1000000000;

插入数据,执行结果如下:

MySQL [test]> INSERT INTO lineitem2 SELECT * FROM lineitem;
Query OK, 6001215 rows affected (1 min 47.312 sec)
Records: 6001215  Duplicates: 0  Warnings: 0

不开启 PDML

可以看到,不开启并行的情况下,单个事务插入 600 万行数据,OceanBase 的耗时为 107 秒。

开启 PDML 执行

下面我们通过添加一个 Hint,开启 PDML 的执行选项。注意再次插入前,我们先将上次插入的数据清空。

TRUNCATE TABLE lineitem2;
INSERT /*+ parallel(16) enable_parallel_dml */ INTO lineitem2 SELECT * FROM lineitem;

来看这次的执行耗时:

obclient> TRUNCATE TABLE lineitem2;
Query OK, 0 rows affected (0.108 sec)
obclient> INSERT /*+ parallel(16) enable_parallel_dml */ INTO lineitem2 SELECT * FROM lineitem;
Query OK, 6001215 rows affected (22.117 sec)
Records: 6001215  Duplicates: 0  Warnings: 0

开启 PDML

可以看到开启 PDML 后,相同的表插入 600 万行数据,OceanBase 数据库的耗时缩短为 22 秒左右。PDML 特性带来的性能提升大约为 5 倍。这一特性可以在用户在需要批量数据处理的场景提供帮助。

数据压缩

OceanBase 数据库基于 LSM Tree 结构开发了自己的存储引擎。其中数据大致被分为基线数据(SSTable)和增量数据(MemTable)两部分,基线数据被保存在磁盘中,增量修改在内存中进行。这使得一方面数据在磁盘中能够以更紧凑的方式存储。除此之外由于在磁盘中的基线数据不会频繁更新,OceanBase 数据库又基于通用压缩算法对基线数据进行了再次压缩,使得数据存储在 OceanBase 数据库中可以获得非常好的压缩比。同时这种数据压缩并未带来查询和写入性能的下降。下面我们介绍 OceanBase 数据库导入大量外部数据并且观察数据压缩比的方法。

数据准备

首先我们使用数据准备工具  CreateData.jar 生成 5 千万行模拟数据到  /home/soft 目录下,生成数据大概需要十几分钟时间,您也可以使用其他工具生成测试数据。

#mkdir /home/soft/
#java -jar CreateData.jar /home/soft/ 50000000
filePath is : /home/soft/
Start Time : 2022-07-10 15:33:00
End Time : 2022-07-10 15:52:53
#du -sh *
10G     t_bigdata_loader.unl

OceanBase 数据库支持多种方式将 csv 格式的数据导入到 OceanBase 数据库中,本文我们介绍通过 Load Data 命令执行。

  1. 首先您需对生成的文件进行命名,并确认实际大小。

    mv t_bigdata_loader.unl t_f1.csv
    du -sh t_f1.csv
    10G     t_f1.csv
  2. 对  t_f1.csv 文件内容查看可知,预先生成好的 csv 文件,通过随机算法,获取了 8 列数据,可对应不同的数据类型。因此在体验 OceanBase 数据压缩特性时,需要在租户下先创建一张表,将 csv 文件中的记录,导入到表中。

    1|1896404182|1980-06-01|2004-10-25 13:30:39|7470.689|33062564.9527|nOLqnBYtnp|BzWYjZjeodtBNzXSMyBduMNzwDPSiVmhVgPJMeEkeAwKBCorzblwovIHDKBsQhbVjQnIdoeTsiLXTNwyuAcuneuNaol|
    2|572083440|2018-11-09|1998-07-11 01:23:28|6891.054|66028434.4013|UzqteeMaHP|vQWbWBXEWgUqUTzqsOSciiOuvWVcZSrlEOQDwDVGmvGRQYWmhCFdEkpsUsqrWEpKtmxSwURHIHxvmlXHUIxmfelYboeGEuScKKqzpuNLryFsStaFTTRqSsVlCngFFjHnEnpaCnWsdwztbiHJyoGkaxrFmyPAmVregfydArrUZsgRqBpQ|
    3|1139841892|2006-10-07|1999-06-26 17:02:22|286.43692|51306547.5055|KJJtylgxkv|BuBdFTBIIFsEPVxsVBRqAnFXSBdtZDgfumUhIx|
    4|1777342512|1982-12-18|2017-11-19 07:56:35|2986.242|85860387.8696|rTkUBWhdPt|JSazOTAmvtCBrINttDwublNJNRFDIiWkHtWZXmWgKHoZCKGqmmETkIcYLXiSgKkoaATNgjvPxVGjeCOODLEWqrQHqowbMjOLOKrtirWEOpUSxiUudZduTCUvZElKzZfggvCBNthwzKJc|
    ....
  3. 在租户  test 下的  test 数据库中创建一张表,表名为  t_f1。详细的租户创建过程,请参考管理租户内容。

    obclient -h127.0.0.1 -P2881 -uroot@test  -Dtest -A -p -c
    obclient [test]> CREATE TABLE t_f1(id DECIMAL(10,0),id2 DECIMAL(10,0),id3 DATE,id4 DATE,id5 FLOAT,id6 FLOAT,id7 VARCHAR(30),id8 VARCHAR(300));

数据导入

我们可以使用 OceanBase 数据库内置的 Load Data 命令导入数据,Load Data 同样支持并行导入。开始导入前进行如下设置。Load Data 命令仅支持数据文件在 OBServer 本地执行,如果您希望远程进行数据导入,可以参考使用 OceanBase 数据库的 obloader 工具。

SET ob_query_timeout=1000000000;
SET ob_trx_timeout=1000000000;
SET GLOBAL secure_file_priv = "";
GRANT FILE ON *.* to username;

注意

由于安全原因,以上授权 SQL 只能使用本地访问执行,不能使用远程 OBClient 执行。即需要在 OBServer 所在机器上登录 OBClient (或者 MySQL 客户端) 执行。

设置完成后,重连会话使设置生效。然后运行导入语句:

load data /*+ parallel(16) */ infile '/home/soft/t_f1.csv' into table t_f1 fields terminated by '\|' lines terminated by '\n';

可以看到,开启并行导入后,10 GB 数据耗时大约 4 分钟。 本文中租户的 CPU 配置为 16 GB,可以根据您的具体配置设置合适的并行度,配置越高导入速度越快。

导入后,进入数据库对该表记录条数及占用空间大小进行查看。

  1. 查看表记录数有 5 千万条。

    obclient [test]> SELECT COUNT(*) FROM t_f1;
    +----------+
    | count(*) |
    +----------+
    | 50000000 |
    +----------+
  2. 对数据库合并。

    为了查看基线数据的压缩效果,我们使用  sys 租户管理员登录,主动触发对数据库进行合并,使增量数据可以和基线数据进行合并与压缩。您可以通过如下的方式手动触发合并。

    obclient -h127.0.0.1 -P2881 -uroot@sys  -Doceanbase -A -p -c
    obclient[oceanbase]> ALTER SYSTEM MAJOR FREEZE;
  3. 当看到如下查询返回 IDLE 时,表示合并完成。

    obclient> SELECT name,info FROM __all_zone WHERE zone='' AND name = 'merge_status';
    +--------------+------+
    | name         | info |
    +--------------+------+
    | merge_status | IDLE |
    +--------------+------+
    1 row in set
  4. 使用 sys 租户查询如下语句,可查看导入至 OceanBase 后的数据存储占用情况。

    obclient [oceanbase]> SELECT b.table_name,svr_ip,role,a.data_size/1024/1024/1024 FROM __all_virtual_meta_table a,__all_virtual_table b WHERE a.role=1 AND a.table_id=b.table_id AND b.table_name='T_F1';
    +------------+---------------+------+----------------------------+
    | table_name | svr_ip        | role | a.data_size/1024/1024/1024 |
    +------------+---------------+------+----------------------------+
    | t_f1       | xxx.xx.xxx.xx |    1 |             6.144531250000 |
    +------------+---------------+------+----------------------------+复制

压缩后的表大小约为 6.145 G,压缩比为 = 10/6.145 = 1.62。


请使用浏览器的分享功能分享到微信等