1. 前言
中启乘数科技是Greenplum解决方案的领先数据库服务商,专注极致的性能优化,为用户提供高性能、大并发和PB级别的数据仓库解决方案,本测试由中启乘数科技数据库专家完成测试。本次测试的使用了以下两个海量数据的场景:
- pgbench 造数据 50亿
- 造sysbench形式的数据近1TB
2. 为什么需要ScaleFlux盘的压缩功能
按ScaleFlux公司对自己的定义:
ScaleFlux是可计算(Computational Storage)技术的行业领先厂商。
这个定义太书面化,我这里简单翻译一下,ScaleFlux主要生产硬件带有透明压缩功能的NVMe盘的厂商,简单说就是提供一块盘,实际容量是3.2T,但是你可以当成9.6T或更大使用。数据存储磁盘时会自动压缩,读取时会自动解压。
我们知道近期硬盘都在涨价,使用压缩功能节省空间,将大大节省我们的成本。
同时我们知道Greenplum数据库本身有压缩功能,为什么还需要在硬件上做压缩呢?最主要的原因是Greenplum的压缩表必须是AO表,AO表有以下限制:
- AO表对于UPDATE和DELETE操作会在表上加表锁,也就是UPDATE和DELETE不能并发。INSERT和INSERT可以并发,但最多支持127个并发插入。
- AO表不支持主键和唯一索引。
- AO表上走索引扫描做等值查询基本只能走Bitmap Index Scan。
而如果我们直接使用ScaleFlux盘的透明压缩功能,就可以使用普通表,就没有了上面的限制。
当然使用ScaleFlux盘的透明压缩功能,对Greenplum集群还带来了以下好处:
- 减少了CPU的占用。我们知道压缩和解压是非常耗费CPU的操作,把这部分工作移动到硬件上,会大大降低压缩和解压对CPU的消耗。
- 提高了性能,使用硬件的压缩功能,速度会更快,延迟更低。
3. 安装ScaleFlux盘和驱动
安装
yum localinstall sfx3xdriver-3.2.XXX.rpm
安装驱动完成后,硬盘就出来了:
[root@csyun01 ~]# lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
sdb 8:16 0 200G 0 disk
├─vgsata01-lv00000002 251:1 0 19.5G 0 lvm
└─vgsata01-lv00000001 251:0 0 29.3G 0 lvm
sfdv0n1 252:0 0 2.9T 0 disk
sdc 8:32 0 200G 0 disk
├─sdc9 8:41 0 8M 0 part
└─sdc1 8:33 0 200G 0 part
sda 8:0 0 200G 0 disk
├─sda2 8:2 0 32G 0 part /
├─sda3 8:3 0 16G 0 part [SWAP]
└─sda1 8:1 0 200M 0 part /boot/efi
盘实际大小为3.2T,我们做成9.6T:
sfx-nvme sfx change-cap /dev/sfdv0n1 -c 9600
把盘格式化为xfs,挂载到/data01:
mkfs.xfs -f -i size=512 -l size=128m,lazy-count=1 -d agcount=16 -L data01 /dev/sfdv0n1
mount -o discard /dev/sfdv0n1 /data01
由于只有一台物理机器, 我们安装LXC容器,做三个容器,相当于三台虚拟机,做成1个MASTER节点2个SEGMENT节点的GREENPLUM,具体做法略。
4. 测试过程与结果
4.1 场景一,使用pgbench造50亿数据
time pgbench -i -s 50000
...
...
4999500000 of 5000000000 tuples (99%) done (elapsed 2124.38 s, remaining 0.21 s).
4999600000 of 5000000000 tuples (99%) done (elapsed 2124.41 s, remaining 0.17 s).
4999700000 of 5000000000 tuples (99%) done (elapsed 2124.47 s, remaining 0.13 s).
4999800000 of 5000000000 tuples (99%) done (elapsed 2124.50 s, remaining 0.08 s).
4999900000 of 5000000000 tuples (99%) done (elapsed 2124.55 s, remaining 0.04 s).
5000000000 of 5000000000 tuples (100%) done (elapsed 2124.59 s, remaining 0.00 s).
vacuum...
set primary keys...
done.
real 103m18.492s
user 21m47.415s
sys 0m33.083s
从上面可以看出插入50亿条数据,时间是2125秒,即不到一个小时,加上后面的vacuum和建主键花了较长的时间,总共是103分18秒。
我们看看压缩率情况:
[root@csyun01 data01]# cat /sys/block/sfdv0n1/sfx_smart_features/sfx_logical_size
1545834440
[root@csyun01 data01]# cat /sys/block/sfdv0n1/sfx_smart_features/sfx_physical_size
234608808
上面的结果中的单位是扇区数,压缩后占用空间为: 234608808/2048=114555MB,压缩前的空间:1545834440/2048=754801MB,压缩比为 6.6:1。压缩率很高的原因是pgbench造出了很多的重复的数据。
顺带pgbench跑一下在50亿数据下的TPC-B的结果值,基本可以跑到8000,还是挺不错的:
[gpadmin@gp01 ~]$ pgbench -P 2 -c 8 -T 1000
starting vacuum...end.
progress: 2.0 s, 2925.4 tps, lat 2.702 ms stddev 2.840
progress: 4.0 s, 3177.5 tps, lat 2.516 ms stddev 0.175
progress: 6.0 s, 3188.5 tps, lat 2.509 ms stddev 0.178
progress: 8.0 s, 3183.5 tps, lat 2.512 ms stddev 0.180
progress: 10.0 s, 3204.4 tps, lat 2.496 ms stddev 0.180
^C
[gpadmin@gp01 ~]$ pgbench -P 2 -c 4 -T 1000
starting vacuum...end.
progress: 2.0 s, 1769.5 tps, lat 2.246 ms stddev 2.702
progress: 4.0 s, 1897.0 tps, lat 2.107 ms stddev 0.173
progress: 6.0 s, 1888.9 tps, lat 2.117 ms stddev 0.179
^C
[gpadmin@gp01 ~]$ pgbench -P 2 -c 16 -T 1000
starting vacuum...end.
progress: 2.0 s, 4589.0 tps, lat 3.411 ms stddev 3.169
progress: 4.0 s, 4942.5 tps, lat 3.236 ms stddev 0.331
progress: 6.0 s, 4913.0 tps, lat 3.256 ms stddev 0.346
progress: 8.0 s, 4894.5 tps, lat 3.268 ms stddev 0.334
progress: 10.0 s, 4813.9 tps, lat 3.323 ms stddev 0.343
progress: 12.0 s, 4917.6 tps, lat 3.253 ms stddev 0.314
progress: 14.0 s, 4992.0 tps, lat 3.204 ms stddev 0.397
^C
[gpadmin@gp01 ~]$ pgbench -P 2 -c 32 -T 1000
starting vacuum...end.
progress: 2.0 s, 7462.5 tps, lat 4.111 ms stddev 3.018
progress: 4.0 s, 8014.9 tps, lat 3.991 ms stddev 0.731
progress: 6.0 s, 7205.8 tps, lat 4.440 ms stddev 0.998
progress: 8.0 s, 8191.8 tps, lat 3.906 ms stddev 0.741
progress: 10.0 s, 8207.9 tps, lat 3.899 ms stddev 0.647
progress: 12.0 s, 8056.0 tps, lat 3.971 ms stddev 0.666
progress: 14.0 s, 8262.9 tps, lat 3.873 ms stddev 0.612
progress: 16.0 s, 8247.1 tps, lat 3.879 ms stddev 0.730
progress: 18.0 s, 7094.0 tps, lat 4.509 ms stddev 1.091
progress: 20.0 s, 7971.3 tps, lat 4.014 ms stddev 0.679
progress: 22.0 s, 7936.6 tps, lat 4.032 ms stddev 3.529
progress: 24.0 s, 8166.1 tps, lat 3.919 ms stddev 0.658
progress: 26.0 s, 8189.0 tps, lat 3.907 ms stddev 0.631
progress: 28.0 s, 8083.3 tps, lat 3.958 ms stddev 0.682
progress: 30.0 s, 7251.7 tps, lat 4.411 ms stddev 1.051
progress: 32.0 s, 8005.4 tps, lat 3.999 ms stddev 0.718
progress: 34.0 s, 8163.5 tps, lat 3.918 ms stddev 0.659
progress: 36.0 s, 8150.6 tps, lat 3.926 ms stddev 0.651
progress: 38.0 s, 8243.0 tps, lat 3.882 ms stddev 0.746
progress: 40.0 s, 8198.4 tps, lat 3.902 ms stddev 0.640
^C
4.2 场景二:造sysbench的数据
用文章 http://blog.osdba.net/538.html 中的gendata工具快速生成数据。
开5个窗口,分别造10亿条数据:
./gendata 1000000000 > 1.dat
./gendata 1000000000 > 2.dat
./gendata 1000000000 > 3.dat
./gendata 1000000000 > 4.dat
./gendata 1000000000 > 5.dat
造出来的文件基本每个近200GB:
[gpadmin@gp01 sysbench_bin]$ ls -l
total 975487196
-rw-rw-r-- 1 gpadmin gpadmin 199777792110 May 18 15:59 1.dat
-rw-rw-r-- 1 gpadmin gpadmin 199777775870 May 18 16:02 2.dat
-rw-rw-r-- 1 gpadmin gpadmin 199777768927 May 18 16:08 3.dat
-rw-r--r-- 1 gpadmin gpadmin 199777776805 May 18 16:09 4.dat
-rw-r--r-- 1 gpadmin gpadmin 199777785304 May 18 16:09 5.dat
-rw-r--r-- 1 gpadmin gpadmin 35147 May 18 14:18 LICENSE
-rw-r--r-- 1 gpadmin gpadmin 3759 May 18 14:18 README.md
-rwx------ 1 gpadmin gpadmin 371 May 18 14:18 bench.sh
-rwxrwxr-x 1 gpadmin gpadmin 8696 May 18 15:32 gendata
-rw-rw-r-- 1 gpadmin gpadmin 2023 May 18 15:29 gendata.c
-rwx------ 1 gpadmin gpadmin 370 May 18 17:52 gpbench.sh
drwxr-xr-x 2 gpadmin gpadmin 34 May 18 14:18 img
drwxr-xr-x 2 gpadmin gpadmin 4096 May 18 14:18 lua
-rwxr-xr-x 1 gpadmin gpadmin 3307216 May 18 14:18 sysbench_mysql
-rwxr-xr-x 1 gpadmin gpadmin 3324397 May 18 14:18 sysbench_ora
-rwxr-xr-x 1 gpadmin gpadmin 3253979 May 18 14:18 sysbench_pg
开5个窗口同往GP里灌数据:
postgres=# copy sbtest1 from '/home/gpadmin/sysbench_bin/1.dat' (format csv);
COPY 1000000000
Time: 24585621.459 ms
postgres=# copy sbtest2 from '/home/gpadmin/sysbench_bin/2.dat' (format csv);
COPY 1000000000
Time: 24877864.760 ms
postgres=# copy sbtest3 from '/home/gpadmin/sysbench_bin/3.dat' (format csv);
COPY 1000000000
Time: 24796154.435 ms
postgres=# copy sbtest4 from '/home/gpadmin/sysbench_bin/4.dat' (format csv);
COPY 1000000000
Time: 24911173.567 ms
postgres=# copy sbtest5 from '/home/gpadmin/sysbench_bin/5.dat' (format csv);
COPY 1000000000
Time: 24524541.338 ms
灌数据基本花了近7个小时,慢的原因是sbtest1~sbtest5上有索引导致的慢:
postgres=# \d sbtest1
Table "public.sbtest1"
Column | Type | Modifiers
--------+----------------+------------------------------------------------------
id | integer | not null default nextval('sbtest1_id_seq'::regclass)
k | integer | not null default 0
c | character(120) | not null default ''::bpchar
pad | character(60) | not null default ''::bpchar
Indexes:
"sbtest1_pkey" PRIMARY KEY, btree (id)
"k_1" btree (k)
Distributed by: (id)
为了验证是否是因为索引导致导入数据变慢,我们把表上的索引删除掉,然后再测试,发现导入不到一个1小时就可以导入:
postgres=# copy sbtest1 from '/home/gpadmin/sysbench_bin/1.dat' (format csv);
COPY 1000000000
Time: 2355138.816 ms
上面的5个COPY同时灌数据是,IO的吞吐量基本在2~3 GB/S,ScaleFlux的IO能力还是很强的。
[root@csyun01 sysbench_bin]# iostat -dmx 2 sfdv0n1
Linux 4.14.35-1902.300.11.el7uek.x86_64 (csyun01) 05/18/2021 _x86_64_ (40 CPU)
Device: rrqm/s wrqm/s r/s w/s rMB/s wMB/s avgrq-sz avgqu-sz await r_await w_await svctm %util
sfdv0n1 0.00 0.31 374.54 1911.78 56.71 564.51 556.47 1.86 0.82 0.69 0.84 0.06 13.31
Device: rrqm/s wrqm/s r/s w/s rMB/s wMB/s avgrq-sz avgqu-sz await r_await w_await svctm %util
sfdv0n1 0.00 13.50 208.00 43936.00 52.00 3058.04 144.29 28.23 0.64 1.69 0.64 0.02 99.75
Device: rrqm/s wrqm/s r/s w/s rMB/s wMB/s avgrq-sz avgqu-sz await r_await w_await svctm %util
sfdv0n1 0.00 2.00 176.50 33779.50 43.99 2796.57 171.32 24.43 0.73 1.55 0.72 0.03 99.70
Device: rrqm/s wrqm/s r/s w/s rMB/s wMB/s avgrq-sz avgqu-sz await r_await w_await svctm %util
sfdv0n1 0.00 0.00 160.00 40108.50 40.00 2558.44 132.15 29.53 0.74 1.69 0.73 0.02 99.85
Device: rrqm/s wrqm/s r/s w/s rMB/s wMB/s avgrq-sz avgqu-sz await r_await w_await svctm %util
sfdv0n1 0.00 12.50 181.50 38898.50 45.38 3059.80 162.73 28.27 0.73 2.13 0.72 0.03 99.85
表的大小:
postgres=# select pg_total_relation_size('sbtest1');
pg_total_relation_size
------------------------
334309294080
(1 row)
postgres=# select pg_relation_size('sbtest1');
pg_relation_size
------------------
282482769920
(1 row)
postgres=# select count(*) from sbtest1;
count
------------
1000000000
(1 row)
Time: 136522.604 ms
我们看看压缩率情况:
[root@csyun01 ~]# cat /sys/block/sfdv0n1/sfx_smart_features/sfx_physical_size
2564817056
[root@csyun01 ~]# cat /sys/block/sfdv0n1/sfx_smart_features/sfx_logical_size
5821770024
上面的结果中的单位是扇区数,压缩后占用空间为: 2564817056/2048/1024=1223GB,压缩前的空间:1545834440/2048=2776GB,压缩比为 2.27:1。压缩率比之前低的原因是sysbench的数据都是通过随机数填充的。
5. 结论
用pgbench造出的大量重复数据,ScaleFlux压缩率可以达到6.6:1,而使用sysbench的随机数生成的数据,压缩率可以达到2.27:1。
在大批量加载数据过程中,ScaleFlux写吞吐量可以达到2~3GB/s。
从上面的数据看,在Greenplum中使用ScaleFlux卡可以收获很好的效果。