简介
sysbench 是一个模块化的、跨平台、多线程基准测试工具,主要用于评估测试各种不同系统参数下的数据库负载情况。本测试使用 sysbench 分别向官方原版 MySQL 和 TerarkSQL 导入 450,000,000 条数据,测试在不同内存下两者的读写性能。
非常值得注意的是,sysbench 测试中默认的数据分布是 special
,表示热点非常集中的数据,从而测试结果主要体现的是缓存的性能。这就是为什么大家经常发现 sysbench 测试出来性能很高,一到生产环境,性能就跪了。
好在 sysbench 也有对其它数据分布的支持,例如 uniform
,即均匀分布
,其测试结果主要体现的是随机访问
的性能。本文中所有的测试均使用 uniform
分布。
测试程序使用 terark/sysbench 1.0.1,我们在原版 sysbench 的基础上添加了一个次级索引范围查询测试。
测试的数据库有:TerarkSQL (下简称 TerarkDB),不开启压缩的官方原版 MySQL(下简称 InnoDB 无压缩)以及开启压缩的官方原版 MySQL(下简称 InnoDB 有压缩)。
测试平台
- CPU: Intel(R) Xeon(R) CPU E5-2630 v3 @ 2.40GHz x2 (共16核32线程)
- 内存: DDR4 16G @ 1866 MHz x 12 (共 192 G)
- SSD: INTEL SSDSC2BP48 0420 IOPS 89000
- 操作系统: CentOS 7
测试中使用的官方原版 MySQL 版本为 Ver 5.6.35 for linux-glibc2.5 on x86_64。
下文 G, GB 指 230,而非 109。
数据导入
测试中使用 sysbench 导入了 450,000,000 条数据,平均每条数据约 196 字节,总大小为 82.1G;另外,有个 Secondary Index,也要占用空间,因为辅助索引列和主键索引列都是 int32,所以逻辑上,对于每条数据,辅助索引的空间占用是 8 字节,从而辅助索引的逻辑空间占用就是 8*45e7 = 3.4G
。所以,数据源的等效尺寸就是 (196+8)*45e7 = 85.5G
。
数据导入后,数据库尺寸大小比较如下:
数据库尺寸 | 数据条数 | 单条尺寸 | 总尺寸 | 索引+数据 | ||
---|---|---|---|---|---|---|
InnoDB 无压缩 | 101 G | 450,000,000 | 196 字节 | 82.1 G | 85.5 G | |
InnoDB 有压缩 | 56 G | |||||
TerarkDB | 51 G |
注1:sysbench 导入的数据是自动生成的,不是真实数据,TerarkDB 对这种假数据的压缩率,远低于对真数据的压缩率。
导入数据所使用的 sysbench 命令如下:
sysbench --report-interval=1 --db-driver=mysql --mysql-port=3306 \
--mysql-user=root --mysql-db=sysbench --mysql-host=127.0.0.1 \
--threads=32 --tables=1 --mysql_storage_engine=innodb \
--table-size=450000000 --rand-type=uniform --create_secondary=on \
/path/to/share/sysbench/oltp_insert.lua prepare
注2:插入时一定要指定 --rand-type 为 uniform,因为其默认值 special 为热点分布,导入的数据不能体现数据库真实的随机读写性能。
测试结果
我们运行了四种测试:
- 主键等值查询(point_select)
- 读写混合查询(point_select90_update10)
- 次级索引等值查询(secondary_random_points100)
- 次级索引范围查询(secondary_random_limit100)
这四种测试分别在 192G、32G、8G 的内存限制下运行,不同的内存限制使用内存挤占工具实现,内存挤占工具挤占一定数量的内存(不可换出)确保数据库所能使用的内存为以上指定值。
每次测试中 InnoDB 的 innodb_buffer_pool_size 总是设置为可用内存的 70%,TerarkDB 的 softZipWorkingMemLimit 和 hardZipWorkingMemLimit 分别设置为可用内存的 1/8 和 1/4.
所有的测试均使用 32 个线程,每次测试前先 warm up 30 秒,每次测试持续 15 分钟。
内存 | 测试类型 | TerarkDB | InnoDB 无压缩 | InnoDB 有压缩 | ||||||
---|---|---|---|---|---|---|---|---|---|---|
QPS | TPS | RPS | QPS | TPS | RPS | QPS | TPS | RPS | ||
192G | point_select | 123,615 | 1,236.15 | 123,615 | 178,282 | 1,782.82 | 178,282 | 158,869 | 1,588.69 | 158,869 |
point_select90_update10 | 101,410 | 1,014.10 | 101,410 | 50,695 | 506.95 | 50,695 | 6,555 | 65.55 | 6,555 | |
secondary_random_points100 | 5,143 | 5,143.00 | 514,300 | 14,278 | 14,278.79 | 1,427,800 | 2,556 | 2,556.01 | 255,601 | |
secondary_random_limit100 | 9,139 | 91.39 | 913,900 | 21,164 | 211.64 | 2,116,400 | 2,749 | 27.49 | 274,900 | |
32G | point_select | 89,998 | 899.98 | 89,998 | 22,301 | 223.01 | 22,301 | 38,328 | 383.28 | 38,328 |
point_select90_update10 | 46,122 | 461.22 | 46,122 | 12,445 | 124.45 | 12,445 | 2,896 | 28.96 | 2,896 | |
secondary_random_points100 | 1,309 | 1,309.22 | 130,922 | 228 | 227.68 | 22,768 | 269 | 269.14 | 26,914 | |
secondary_random_limit100 | 1,743 | 17.43 | 174,300 | 232 | 2.32 | 23,200 | 398 | 3.98 | 39,800 | |
8G | point_select | 68,864 | 688.64 | 68,864 | 23,829 | 238.29 | 23,829 | 29,016 | 290.16 | 29,016 |
point_select90_update10 | 29,916 | 299.16 | 29,916 | 12,787 | 127.87 | 17,787 | 2,103 | 21.03 | 2,103 | |
secondary_random_points100 | 841 | 841.00 | 84,100 | 172 | 171.63 | 17,163 | 69 | 69.77 | 6,977 | |
secondary_random_limit100 | 925 | 9.25 | 92,500 | 251 | 2.51 | 25,100 | 311 | 3.11 | 31,100 |
注3:
上表中 QPS 表示 Queries Per Second,TPS 表示 Transactions Per Second,RPS 表示 Rows Per Second。
将上表中的 RPS 数据做成更直观的图表,如下:
192G 内存对 TerarkDB 和 InnoDB 都够用,实际上,TerarkDB 只使用了大约 52G,InnoDB 则耗尽了所有内存(进程内存 + 系统缓存)。
TerarkDB 的只读性能低于 InnoDB,主要是因为 MyRocks 适配层带来的性能损失(相比引擎层损失了 10 倍以上的性能)。
TerarkDB 的读写混合性能高于 InnoDB,是因为 TerarkDB 通过 RocksDB 使用了 LSM Tree,随机写性能从根上就远优于 InnoDB 的 BTree。
32G 内存,TerarkDB 不太够用,但 InnoDB 很不够用,TerarkDB 尽管有 MyRocks 适配层带来的性能损失,但 InnoDB 因为内存不够受限于 IO 瓶颈 ,从而 TerarkDB 的性能远高于 InnoDB。
8G 内存对 TerarkDB 和 InnoDB 都很不够用,TerarkDB 的 IO 也成为瓶颈,但 InnoDB 的内存缺口更大,从而 TerarkDB 的性能仍远高于 InnoDB。
测试类型说明
1. point_select
主键等值查询,测试程序每次随机生成一个 ID 值,然后查询主键与之相等的记录。测试的每个 transaction 里包含 100 个主键等值查询 query,故每个 transaction 会访问 100 行数据。
示例 SQL:
select c from sbtest1 where id = ID;
sysbench 命令
sysbench --time=900 --report-interval=1 --db-driver=mysql --mysql-port=3306 \ --mysql-user=root --mysql-db=sysbench --mysql-host=127.0.0.1 \ --threads=32 --warmup-time=30 --distinct_ranges=0 \ --sum_ranges=0 --index_updates=0 --range_size=100 \ --delete_inserts=0 --tables=1 --mysql_storage_engine=rocksdb \ --non_index_updates=0 --table-size=450000000 --simple_ranges=0 --secondary_ranges=0\ --order_ranges=0 --range_selects=off --point_selects=100 \ --rand-type=uniform --skip_trx=on /path/to/share/sysbench/oltp_read_only.lua run
2. point_select90_update10
读写混合测试,除上述主键等值查询外,还会随机生成一个 ID,然后更新主键与该 ID 相等的记录的 c 值。测试的每个 transaction 包含 90 个主键等值查询 query,和 10 个非主键更新 query,故每个 transaction 会访问 100 行数据,并更新 10 行数据。
- 示例 SQL: ``` select c from sbtest1 where id = ID;
update sbtest1 set c = C where id = ID;
- sysbench 命令
sysbench --time=900 --report-interval=1 --db-driver=mysql --mysql-port=3306 \ --mysql-user=root --mysql-db=sysbench --mysql-host=127.0.0.1 \ --threads=32 --warmup-time=30 --distinct_ranges=0 \ --sum_ranges=0 --index_updates=0 --range_size=100 \ --delete_inserts=0 --tables=1 --mysql_storage_engine=rocksdb \ --non_index_updates=10 --table-size=450000000 --simple_ranges=0 --secondary_ranges=0\ --order_ranges=0 --range_selects=off --point_selects=90 \ --rand-type=uniform --skip_trx=on /path/to/share/sysbench/oltp_read_write.lua run
#### 3. secondary_random_points100
次级索引等值查询,测试程序随机生产 100 个 key,然后使用 where in 语法随机读取这 100 个 key 对应的 100 行数据。
测试的每个 transaction 包含一个 Query,每个 Query 对次级索引进行 100 次随机搜索,每次都需要进行回表操作(先从次级键拿到主键,再用主键取数据),从而每个 transaction 需要对存储引擎进行 200 次随机访问。
- 示例 SQL:
select id, k, c, pad from sbtest1 where k in (k1, k2, k3, ..., k100);
- sysbench 命令
sysbench --time=900 --report-interval=1 --db-driver=mysql --mysql-port=3306 \ --mysql-user=root --mysql-db=sysbench --mysql-host=127.0.0.1 \ --threads=32 --warmup-time=30 --tables=1 --table-size=450000000 \ --rand-type=uniform --skip_trx=on \ --random_points=100 /path/to/share/sysbench/select_random_points.lua run
#### 4. secondary_random_limit100
次级索引范围查询,该查询为我们新添加的测试,用来测试主索引的随机读性能: 次级 Key 是随机生成的,次级 Key 按大小顺序映射到主键,得到的主键序列就是随机顺序,所以,这样的访问,就是次级 Key 的顺序访问再加主键的随机访问。
测试的每个 transaction 包含 100 个次级索引范围查询 query,每个 query 会访问 100 行数据,从而每个 transaction 会访问 10,000 行数据。
- 示例 SQL:
select c from sbtest1 where k >= K limit 100;
- sysbench 命令
sysbench --time=900 --report-interval=1 --db-driver=mysql --mysql-port=3306 \ --mysql-user=root --mysql-db=sysbench --mysql-host=127.0.0.1 \ --threads=32 --warmup-time=30 --distinct_ranges=0 \ --sum_ranges=0 --index_updates=0 --range_size=100 \ --delete_inserts=0 --tables=1 --mysql_storage_engine=rocksdb \ --non_index_updates=0 --table-size=450000000 --simple_ranges=0 --secondary_ranges=100 \ --order_ranges=0 --range_selects=on --point_selects=0 \ --rand-type=uniform --skip_trx=on /path/to/share/sysbench/oltp_read_only.lua run ```