kunpengcompute / kunpengcompute.github.io

Kunpeng Tech Blog: https://kunpengcompute.github.io/
Apache License 2.0
17 stars 5 forks source link

MariaDB的S3存储引擎在arm64平台上的表现 #61

Open zhaorenhai opened 3 years ago

zhaorenhai commented 3 years ago

作者: zhaorenhai

MariaDB除了默认的InnoDB存储引擎以外,还有很多其他的存储引擎,这些引擎在某些方面也是比较有用的。从这篇文章开始,我们开始关注一下这些非默认的存储引擎在arm64平台上的表现。

我们第一个研究的存储引擎是S3。 S3存储引擎是在10.5版本才引进的一个新功能。S3存储引擎其实就把数据存储在支持S3协议的云存储上。当前存储在上面的表只能读,不能写。可以通过改变表的存储引擎的方式,把数据传到S3上面去,也可以对S3存储引擎的表进行增加列和删除列,也可以建立索引,但是就是不能直接对表增删改(后续版本可能会有这些功能)。看到这里读者应该会有疑问,S3存储引擎有啥用?其实在对一些不再更新的数据,但是数据量又比较大,而且数据比较重要,又不能删除的场景比较有用,这时候就可以把这些表的存储引擎改为S3,因为S3存储引擎相对于本地存储比较便宜,而且可靠,是一个很好的选择。

下面我们就简单的从几个方面看一下S3存储引擎在arm64平台上的表现

首先我们先跑一下S3存储引擎的测试用例,看看在arm64平台上是否都能通过(MariaDB当前还没有把S3存储引擎相关的测试用例作为默认必跑的测试用例,这个文档里有提到:https://mariadb.com/kb/en/s3-storage-engine/ ),然后会看看S3存储引擎在arm64上功能和性能方面的情况。

测试平台用的是华为云的鲲鹏虚拟机,OS是Ubuntu18.04。我们S3存储服务用的是华为云的OBS服务,提前创建好访问key和密钥,桶,后续测试时需要配置(注意OBS选择的存储区域最好和测试用的鲲鹏虚拟机在同一个区域,以减少网络延迟。OBS相关指导请参考华为云官方指导,这里不再详述)。

我们在OS上新建一个用户adduser mariadb,后续所有的工作都在这个用户下进行。

从github上下载一下MariaDB最新版本的源码,并编译

su - mariadb
sudo apt-get install build-essential libncurses5-dev gnutls-dev libcurl4-gnutls-dev 
sudo apt-get install zlib1g-dev ccache libnuma-dev libxml2-dev cmake bison
git clone https://github.com/mariadb/server
cd server
git submodule update --init
cd ..
mkdir build-mariadb-server
cd build-mariadb-server
#加入RelWithDebInfo选项,是为了后续如果需要进行对性能分析的话,可以用perf工具看到代码
cmake ../server -DCMAKE_BUILD_TYPE=RelWithDebInfo
cmake --build .

测试用例

编辑测试用例需要的配置文件:

vi ~/server/mysql-test/suite/s3/my.cnf

最终配置格式如下:

!include include/default_mysqld.cnf
!include include/default_client.cnf

[mysqld.1]
#当前S3存储引擎在10.6版本的成熟度是gamma,还不是stable,没有默认被加载,需要手动配置一下
plugin-maturity = gamma
plugin-load-add=@ENV.HA_S3_SO
s3=ON
s3-host-name=obs.cn-north-4.myhuaweicloud.com
#之前在OBS上创建的桶的名字
s3-bucket=mariadb
s3-access-key=please replace with your access key
s3-secret-key=please replace with your secret key
#OBS区域
s3-region=cn-north-4

编辑如下配置文件

vi ~/server/mysql-test/suite/s3/slave.cnf

最终配置格式如下:

[mysqld.2]
plugin-maturity = gamma
plugin-load-add=@ENV.HA_S3_SO
s3=ON
s3-slave-ignore-updates=1
s3-host-name=obs.cn-north-4.myhuaweicloud.com
s3-bucket=mariadb
s3-access-key=please replace with your access key
s3-secret-key=please replace with your secret key
s3-region=cn-north-4

开始跑测试用例

cd ~/build-mariadb-server/mysql-test
./mysql-test-run --suite=s3

输出如下:

Logging: /home/mariadb/server/mysql-test/mysql-test-run.pl  --suite=s3
vardir: /home/mariadb/build-mariadb-server/mysql-test/var
Checking leftover processes...
Removing old var directory...
Creating var directory '/home/mariadb/build-mariadb-server/mysql-test/var'...
Checking supported features...
MariaDB Version 10.6.0-MariaDB

 - SSL connections supported
   Using suites: s3
   Collecting tests...
   Installing system database...

==============================================================================

TEST                                      RESULT   TIME (ms) or COMMENT
--------------------------------------------------------------------------

worker[1] Using MTR_BUILD_THREAD 300, with reserved ports 16000..16019
s3.partition_create_fail                 [ skipped ]  Requires debug build
s3.encryption                            [ pass ]    777
s3.partition_move 'innodb'               [ pass ]   4059
s3.alter 'innodb'                        [ pass ]   5361
s3.innodb 'innodb'                       [ pass ]   1444
s3.alter2                                [ pass ]   1702
s3.partition                             [ pass ]  24858
s3.no_s3                                 [ pass ]      7
s3.arguments                             [ pass ]   1231
s3.basic                                 [ pass ]    830
s3.discovery                             [ pass ]   3288
s3.amazon                                [ skipped ]  Not connected to AWS
s3.backup                                [ pass ]    581
s3.mysqldump                             [ pass ]   3156
s3.select                                [ pass ]    600
s3.unsupported                           [ pass ]    329
s3.replication_delayed 'innodb,mix'      [ pass ]   3444
s3.replication_mixed 'mix'               [ pass ]   8435
s3.replication_partition 'innodb,mix'    [ pass ]  20100

s3.replication_stmt 'stmt'               [ pass ]   8967
--------------------------------------------------------------------------

The servers were restarted 10 times
Spent 89.169 of 107 seconds executing testcases

Completed: All 18 tests were successful.

2 tests were skipped, 1 by the test itself.

我们可以看到,除了一个测试用例需要debug版本来测,另外一个需要连接AWS(我们用的是华为云)来测,被skip了以外,其余测试用例全部都是成功的。说明在arm64平台上,S3存储引擎的基本功能是没问题的。

性能

接下来我们看看S3性能方面的情况。

首先配置一下mysql客户端路径,我们使用刚刚编译出来的最新mysql客户端,将如下代码加入~/.bashrc

export PATH=~/build-mariadb-server/client:$PATH  

然后

source ~/.bashrc

编辑配置文件:

 vi ~/mariadb.cnf

按如下格式输入内容:

[mariadbd]
#数据文件目录
datadir = /home/mariadb/data/dir
#path to source dir + sql/share
lc_messages_dir = /home/mariadb/server/sql/share

innodb_buffer_pool_size = 8G
innodb_log_file_size = 1G
innodb_flush_method = O_DIRECT

plugin-maturity = gamma
plugin_dir = /home/mariadb/build-mariadb-server/storage/maria
plugin-load-add=ha_s3
s3=ON
s3-host-name=obs.cn-north-4.myhuaweicloud.com
s3-bucket=mariadb
s3-access-key=please replace with your access key 
s3-secret-key=please replace with your secret key
s3-region=cn-north-4

然后启动数据库:

mkdir -p /home/mariadb/data/dir
cd ~/build-mariadb-server
./scripts/mysql_install_db --srcdir=../server --defaults-file=~/mariadb.cnf
sql/mysqld --defaults-file=~/mariadb.cnf

数据库启动成功以后,我们创建一些测试数据

新启动一个shell窗口,登陆到mariadb用户,登陆数据库

mysql --socket=/tmp/mysql.sock

执行如下sql创建一个测试表

create table test.s3test(id int, description varchar(40));

然后退出到shell环境,准备给这个表导入大量的数据。

用shell脚本生成了一个大小为2.6G的csv文件,大概6000多万条记录,里面第一列为数字,第二列为随机生成的字符串,命名为s3test.csv

用如下命令导入数据库:

mysqlimport --socket=/tmp/mysql.sock --fields-terminated-by=, test /home/mariadb/s3test.csv

导入数据库以后,查看数据库文件 /home/mariadb/data/dir/test/s3test.ibd,数据库文件的大小为4.4G。

接下来我们测试一下,将这个4.4G大小的表,存储到S3存储引擎,时间需要多久。

登陆到数据库,执行如下sql

alter table test.s3test engine=s3;

输出如下

Query OK, 63649280 rows affected (2 min 49.886 sec)
Records: 63649280  Duplicates: 0  Warnings: 0

可以看到4.4G大小的表,存储引擎改为S3,只用了两分钟49秒,速度还是挺快的。

我们再看本地的数据文件/home/mariadb/data/dir/test/s3test.ibd已经不存在了,说明表的确已经被存到了云存储上面。

然后我们查看一下OBS上面的文件。

下载一个obsutil工具:

wget https://obs-community.obs.cn-north-1.myhuaweicloud.com/obsutil/current/obsutil_linux_arm64.tar.gz
tar -zxvf obsutil_linux_arm64.tar.gz
cd obsutil_linux_arm64_5.2.10
#配置obsutil工具
./obsutil config -i=accesskey -k=secrectkey -e=obs.cn-north-4.myhuaweicloud.com

查询一下OBS上的数据

./obsutil ls obs://mariadb/test/s3test/

输出的大小如下, 为3.22GB, 比innodb的存储还要小一点:

Total size of prefix [test/s3test/] is: 3.22GB
Folder number is: 0
File number is: 826

接下来我们查询一下数据,看看速度怎么样,登陆mariadb数据库,输入如下sql

select * from test.s3test where id = 8;

输出除了结果以外,显示用的时间如下:

512 rows in set (1 min 17.121 sec)

从6000多万条无索引的记录里,查询512条记录,大概用了1分钟17秒,速度还是可以接受的。

接下来我们看看建索引的速度,以及建索引后查询的速度。

MariaDB [(none)]> alter table test.s3test add index idx_id(id);
Query OK, 63649280 rows affected (7 min 12.253 sec)
Records: 63649280  Duplicates: 0  Warnings: 0

可以看到创建索引用了7分钟。

重新查询一下

MariaDB [(none)]> pager md5sum; select * from test.s3test where id = 8;
46ebf3c834a4023edec7fe311f50438d  -
512 rows in set (25.146 sec)

可以看到这次速度快了一点,25秒。

我们看看索引占用的大小

./obsutil ls obs://mariadb/test/s3test/

输出的大小为3.81GB,比不建索引多了600M,说明索引占用了600M左右

Total size of prefix [test/s3test/] is: 3.81GB
Folder number is: 0
File number is: 979

可以证实一下

./obsutil ls obs://mariadb/test/s3test/index

输出如下,的确占用600M左右

Total size of prefix [test/s3test/index] is: 609.02MB
Folder number is: 0
File number is: 153

接下来我们把索引删掉,看看用时多久。

MariaDB [(none)]> alter table test.s3test drop index idx_id;
Query OK, 63649280 rows affected (4 min 18.969 sec)
Records: 63649280  Duplicates: 0  Warnings: 0

删除索引用了4分钟。

把表的存储引擎改为InnoDB,看看用时多久。

MariaDB [(none)]> alter table test.s3test engine=innodb;
Query OK, 63649280 rows affected (6 min 6.302 sec)
Records: 63649280  Duplicates: 0  Warnings: 0

用了6分钟左右。

和InnoDB对比

现在表在本地数据库,存储引擎是InnoDB,我们把以上操作重新来一遍,对比一下InnoDB引擎和S3引擎的性能。

MariaDB [(none)]> pager md5sum;select * from test.s3test where id = 8;
PAGER set to 'md5sum'
46ebf3c834a4023edec7fe311f50438d  -
512 rows in set (30.218 sec)

MariaDB [(none)]> alter table test.s3test add index idx_id(id);
Query OK, 0 rows affected (2 min 1.309 sec)
Records: 0  Duplicates: 0  Warnings: 0

MariaDB [(none)]> pager md5sum;select * from test.s3test where id = 8;
PAGER set to 'md5sum'
46ebf3c834a4023edec7fe311f50438d  -
512 rows in set (0.009 sec)

MariaDB [(none)]> alter table test.s3test drop index idx_id;
Query OK, 0 rows affected (0.009 sec)
Records: 0  Duplicates: 0  Warnings: 0

可以看出来,本地InnoDB引擎还是比S3要快不少,除了索引查询和删除索引操作外,无索引查询和创建索引两个操作并没有数量级上的差异,S3的速度还是可以接受的。

增大S3 Page Buffer之后的性能

我们把S3存储引擎的Buffer改大,看看性能有没有改善。

vi ~/mariadb.cnf

添加如下配置,将s3的page buffer的大小设置为5个G(默认是128M)

s3_pagecache_buffer_size=5368709120

重启数据库

现在我们再来重复一遍之前的操作:

MariaDB [(none)]> alter table test.s3test engine=s3;
Query OK, 63649280 rows affected (5 min 8.340 sec)
Records: 63649280  Duplicates: 0  Warnings: 0

MariaDB [(none)]> pager md5sum;select * from test.s3test where id = 8;
PAGER set to 'md5sum'
46ebf3c834a4023edec7fe311f50438d  -
512 rows in set (39.110 sec)

MariaDB [(none)]> pager md5sum;select * from test.s3test where id = 8;
PAGER set to 'md5sum'
46ebf3c834a4023edec7fe311f50438d  -
512 rows in set (10.019 sec)

MariaDB [(none)]> alter table test.s3test add index idx_id(id);
Query OK, 63649280 rows affected (5 min 45.067 sec)
Records: 63649280  Duplicates: 0  Warnings: 0

MariaDB [(none)]> pager md5sum;select * from test.s3test where id = 8;
PAGER set to 'md5sum'
46ebf3c834a4023edec7fe311f50438d  -
512 rows in set (17.479 sec)

MariaDB [(none)]> pager md5sum;select * from test.s3test where id = 8;
PAGER set to 'md5sum'
46ebf3c834a4023edec7fe311f50438d  -
512 rows in set (0.015 sec)

MariaDB [(none)]> alter table test.s3test drop index idx_id;
Query OK, 63649280 rows affected (4 min 46.552 sec)
Records: 63649280  Duplicates: 0  Warnings: 0

MariaDB [(none)]> alter table test.s3test engine=innodb;
Query OK, 63649280 rows affected (6 min 28.248 sec)
Records: 63649280  Duplicates: 0  Warnings: 0

可以看到改变引擎,创建删除索引等操作并没有实质上的提升,但是查询数据,特别是第二遍以后的查询数据,速度有数量级上的提升,主要应该归功于大的Buffer对数据的缓存。

启用压缩之后的性能

接下来我们测试一下创建表的时候,加上压缩参数 COMPRESSION_ALGORITHM=zlib,看看效果如何。

MariaDB [(none)]> alter table test.s3test engine=s3  COMPRESSION_ALGORITHM=zlib;
Query OK, 63649280 rows affected (6 min 21.659 sec)
Records: 63649280  Duplicates: 0  Warnings: 0

时间用了6分多钟,比不压缩长了一倍多一点。我们看下空间能节省多少。

./obsutil ls obs://mariadb/test/s3test/
Total size of prefix [test/s3test/] is: 1.51GB
Folder number is: 0
File number is: 826

可以看到空间节省了一半以上。不过我们的数据是随机的,如果是现实中有规律的数据,估计能有更高的压缩率。另外我们用了默认大小的4MB的块,如果把块的大小改大点,估计压缩率也会有提升。

我们看看查询速度怎么样:

MariaDB [(none)]> pager md5sum;select * from test.s3test where id = 8;
PAGER set to 'md5sum'
46ebf3c834a4023edec7fe311f50438d  -
512 rows in set (56.610 sec)

MariaDB [(none)]> pager md5sum;select * from test.s3test where id = 8;
PAGER set to 'md5sum'
46ebf3c834a4023edec7fe311f50438d  -
512 rows in set (10.110 sec)

可以看到首次查询,比没有压缩时慢了不到一倍,还是可以接受的,第二次查询,由于大的缓存的存在,压缩和没压缩的速度都是一样的。

再看看建立索引的情况:

MariaDB [(none)]> alter table test.s3test add index idx_id(id);
Query OK, 63649280 rows affected (9 min 26.030 sec)
Records: 63649280  Duplicates: 0  Warnings: 0

耗时了9分钟,也是慢了不到一倍。

看看索引占用的空间:

./obsutil ls obs://mariadb/test/s3test/index
Total size of prefix [test/s3test/index] is: 261.54MB
Folder number is: 0
File number is: 153

可以看到启用压缩以后,索引也变小了不少,比不压缩时的一半还要小一点。

再看看查询的情况:

MariaDB [(none)]> pager md5sum;select * from test.s3test where id = 8;
PAGER set to 'md5sum'
46ebf3c834a4023edec7fe311f50438d  -
512 rows in set (27.094 sec)

MariaDB [(none)]> pager md5sum;select * from test.s3test where id = 8;
PAGER set to 'md5sum'
46ebf3c834a4023edec7fe311f50438d  -
512 rows in set (0.009 sec)

第一次查询和没压缩时相比,慢了不到一倍,第二次查询由于大的缓存的存在,就和没压缩时一样了。

最后看看删除索引和将引擎改回InnoDB的耗时:

MariaDB [(none)]> alter table test.s3test drop index idx_id;
Query OK, 63649280 rows affected (6 min 39.382 sec)
Records: 63649280  Duplicates: 0  Warnings: 0

MariaDB [(none)]> alter table test.s3test engine=innodb;
Query OK, 63649280 rows affected (6 min 36.595 sec)
Records: 63649280  Duplicates: 0  Warnings: 0

删除索引慢了不到一倍,改变引擎和没有压缩时耗时一样。

总结

通过我们的测试,可以发现,S3存储引擎在arm64上工作良好,性能也不错。

我们把上面测试的结果通过一个表格总结一下:

 / InnoDB S3 with default options S3 after setting pagecache buffer size to 5G S3 after compression enabled and page buffer size 5G
Altering table to S3 / 2 min 49.886 sec 5 min 8.340 sec 6 min 21.659 sec
Query without index 30.218 sec 1 min 17.121 sec 39.110 sec 56.610 sec
Query without index 2nd time 28.628 sec 51.305 sec 10.019 sec 10.110 sec
Creating index 2 min 1.309 sec 7 min 12.253 sec 5 min 45.067 sec 9 min 26.030 sec
Query with index 0.009 sec 25.146 sec 17.479 sec 27.094 sec
Query with index 2nd time 0.002 sec 29.264 sec 0.015 sec 0.009 sec
Dropping index 0.009 sec 4 min 18.969 sec 4 min 46.552 sec 6 min 39.382 sec
Altering table to InnoDB / 6 min 6.302 sec 6 min 28.248 sec 6 min 36.595 sec
Table size 4.4GB 3.22GB 3.22GB 1.51GB
Index size 1.1GB 609.02MB 609.02MB 261.54MB

参考链接

https://mariadb.com/kb/en/s3-storage-engine/

https://mariadb.com/kb/en/plugin-overview/#installing-a-plugin

https://www.percona.com/blog/2020/07/17/mariadb-s3-engine-implementation-and-benchmarking/

https://blog.csdn.net/weixin_39132936/article/details/103260024

https://support.huaweicloud.com/obs/index.html