TokuDB 性能测试报告

作者介绍:吴双桥 腾讯云数据库工程师

一 、背景介绍

近年来,TokuDB 作为 MySQL 的大数据( Big Data )存储引擎受到人们的普遍关注。其架构的核心基于一种新的叫做分形树( Fractal Trees )的索引数据结构,该结构是缓存无关的,即使索引数据大小超过内存性能也不会下降,也即没有内存生命周期和碎片的问题。

特别引人注意的是,TokuDB 拥有很高的压缩比(官方称最大可达25倍),可以在很大的数据上创建大量的索引,并保持性能不下降。同时,TokuDB 支持 ACID 和 MVCC,还有在线修改表结构(Live Schema Modification)以及增加的复制性能等特性,使其在某些特定的应用领域(如日志存储与分析)有着独特的优势。

在 TokuDB 的应用场景中,通常是数据库插入操作的量远远大于读取的量,因而本次测试主要针对 TokuDB 的插入性能以及压缩比,以 InnoDB 作为参考基准。

二、测试环境搭建

测试使用的机器为高配机型,内存大于100G,CPU 型号为 Intel(R) Xeon(R) CPU E5 系列,数据盘使用的是 SSD 硬盘。

MySQL TokuDB 版本使用的是 5.6.28-76.1,按照 Percona 网站上的安装方法使用插件的方式进行安装,见官网教程。使用MySQL命令查看:

+--------------------+---------+--------------+------+------------+
| Engine             | Support | Transactions | XA   | Savepoints |
+--------------------+---------+--------------+------+------------+
| InnoDB             | YES     | YES          | YES  | YES        | 
| CSV                | YES     | NO           | NO   | NO         | 
| MyISAM             | YES     | NO           | NO   | NO         | 
| BLACKHOLE          | YES     | NO           | NO   | NO         | 
| MEMORY             | YES     | NO           | NO   | NO         | 
| TokuDB             | DEFAULT | YES          | YES  | YES        | 
| MRG_MYISAM         | YES     | NO           | NO   | NO         | 
| ARCHIVE            | YES     | NO           | NO   | NO         | 
| FEDERATED          | NO      | NULL         | NULL | NULL       | 
| PERFORMANCE_SCHEMA | YES     | NO           | NO   | NO         | 
+--------------------+---------+--------------+------+------------+

可以看到 TokuDB 引擎已经就绪,并被设置为了默认的存储引擎。

三、测试工具与变量

1、测试工具选择

现在开源可用的 MySQL 基准测试工具有很多,如mysqlslap,MySQL Benchmark Suite,Super Smack,Database Test Suite,TPCC 和 sysbench 等。综合工具的功能、易用性还有流行程度,最终选定操作简单但功能强大的 sysbench 作为测试工具。在 sysbench 0.5版本中,已经开始支持Lua脚本,使用修改起来非常灵活。另外,测试压缩比直接使用的 mysqldump 工具。

2、测试变量

插入性能相关的变量

除去根据机器硬件特性配置的常规优化参数,对于存储引擎插入性能影响最大的是:是否将事务和binlog同步刷新到硬盘。

需要特别说明的是,还有一个比较重要的指标,即是否开启了 DIRECT IO 功能,由于在测试环境 InnoDB 开启了 DIRECT IO ,并能提高整体的性能,而 TokuDB 在测试机型上无法开启 DIRECT IO 功能,所以在这点上 InnoDB 有相对的优势。

InnoDB 相关

对于 InnoDB 来说,控制这个功能的参数为innodb_flush_log_at_trx_commitsync_binloginnodb_flush_log_at_trx_commit参数指定了InnoDB在事务提交后的日志写入频率。具体来说:

  1. innodb_flush_log_at_trx_commit取值为 0 时,log buffer 会 每秒写入到日志文件并刷写(flush)到硬盘。但每次事务提交不会有任何影响,也就是 log buffer 的刷写操作和事务提交操作没有关系。在这种情况下,MySQL性能最好,但如果 mysqld 进程崩溃,通常会导致最后 1s 的日志丢失。
  2. 当取值为 1 时,每次事务提交时,log buffer 会被写入到日志文件并刷写到硬盘。这也是默认值。这是最安全的配置,但由于每次事务都需要进行硬盘I/O,所以也最慢。
  3. 当取值为 2 时,每次事务提交会写入日志文件,但并不会立即刷写到硬盘,日志文件会每秒刷写一次到硬盘。这时如果 mysqld 进程崩溃,由于日志已经写入到系统缓存,所以并不会丢失数据;在操作系统崩溃的情况下,通常会导致最后 1s 的日志丢失。 在实际的生产系统中,innodb_flush_log_at_trx_commit会在1和2之间选择。一般来说,对数据一致性和完整性要求比较高的应用场景,会将其值设置为1。

sync_binlog参数指定了 MySQL 的二进制日志同步到硬盘的频率。如果MySQL autocommit开启,那么每个语句都写一次binlog,否则每次事务写一次。

  1. 默认值为 0,不主动同步binlog的写入,而依赖于操作系统本身不定期把文件内容flush到硬盘。
  2. 设置为 1 时,在每个语句或者事务后会同步一次binlog,即使发生意外崩溃时也最多丢失一个事务的日志,因而速度较慢。

通常情况下,innodb_flush_log_at_trx_commitsync_binlog配合起来使用,本次性能测试覆盖了同步刷新日志和异步刷新日志两种策略。

TokuDB 相关

TokuDB中与InnoDB类似的指标为tokudb_commit_synctokudb_fsync_log_period。与innodb_flush_log_at_trx_commit的含义类似,tokudb_commit_sync指定当事务提交的时候,是否要刷新日志到硬盘上。

  1. 默认开启,值为1。也就是每次事务提交时,log buffer 会被写入到日志文件并刷写到硬盘。
  2. 如果设置为 0,每次事务提交会写入日志文件,但并不会立即刷写到硬盘,日志文件会每隔一段时间刷写一次到硬盘。这个时间间隔由tokudb_commit_sync指定。

tokudb_fsync_log_period指定多久将日志文件刷新到硬盘,TukuDB的log buffer总大小为 32 MB且不可更改。默认为 0 秒,此时如果tokudb_commit_sync设置为开启,那么这个值默认为 1 分钟。

tokudb_commit_synctokudb_fsync_log_period通常也是配合起来使用,本次性能测试覆盖了两种典型的组合策略。

压缩比相关的变量

大多数选择使用TokuDB的场景,都非常重视它的存储压缩比,因而在实际应用场景中总会配套使用某种压缩算法。当前TokuDB支持的压缩算法有,quicklz, zlib, lzma, snappy,当然还有不压缩uncompressed。关于压缩算法的讨论,可以参考官方博客的一篇分析文章

本次测试会结合真实的数据来从压缩比、耗时两个方面来检验上面几个不同的压缩算法。TokuDB可以通过在配置文件中设置tokudb_row_format来指定不同的压缩算法,它们的取值分别是:TOKUDB_QUICKLZ, TOKUDB_ZLIB, TOKUDB_LZMATOKUDB_SNAPPY。值得注意的是,zlib算法是TokuDB官方最新版本的默认算法,也是现今支持TokuDB的云服务商的默认推荐算法。

sysbench压缩工具相关的变量

sysbench针对mysql压测的参数有很多,这里选取的是与实际应用场景最为相关的两个参数:表数量以及线程数量。表数量对应的是数据库实际在同时写入的表的数量,线程数对应的到MySQL数据库上的连接。其他的参数,如表的大小,是否是事务等可能影响整体的插入性能,但影响并不显著,这里只选取最主要的两个参数进行分析。

3、测试方法

本测试的采用的方式为经典的控制变量法。这里的变量有:采用的存储引擎类型,是否同步刷新日志,采用的压缩算法,以及另外两个与sysbench相关的参数:压测的线程数量和压测的表数量。其中,压缩算法的选择只是在四种算法中选择一种,所以并不与其他变量交叉测试。这样以存储引擎和同步刷新日志来划分测试,可以将整个测试数据分为四个大类:

  1. InnoDB & 同步刷新日志;
  2. InnoDB & 异步刷新日志;
  3. TokuDB & 同步刷新日志;
  4. TokuDB & 异步刷新日志。

在每个大类下,对压测线程数量和压测表数量进行交叉测试。压测表数量取值可能为[1, 2, 4, 8, 12, 16],线程数的可能取值为[1, 2, 4, 8, 16, 24, 32, 48, 64, 80],因而每个大类下进行6 * 10 = 60 次压测,每次压测写入2,000,000 条数据,对每次压测进行插入性能统计。

四、测试结果分析

1、InnoDB & 同步刷新日志

innodb_flush_log_at_trx_commit设置为1,sync_binlog设置为1,也即是保证数据最安全:同步刷新log到硬盘,并且针对每个事务同步一次binlog。测试的情况见下表:

表数/插入TPS/线程数

1

2

4

8

12

16

1

5645.54

5678.40

5711.15

5687.44

5660.76

5708.54

2

10995.42

10921.06

11023.25

11017.88

11038.06

10902.12

4

18732.14

18724.20

18882.65

18935.62

18890.46

17997.52

8

33291.35

33379.37

33372.19

33842.15

30576.58

34048.53

16

54560.36

56346.20

57358.33

57454.11

57571.72

57989.96

24

66230.44

70813.87

73871.31

68764.22

68019.27

67538.82

32

66855.54

80153.06

84885.82

84387.96

76404.04

84920.13

48

56788.96

85778.22

93914.45

97055.96

84041.31

96790.49

64

55640.96

83342.88

95736.42

92667.25

96560.51

83598.00

80

58408.18

75858.18

60683.99

60491.26

60177.24

64290.13

用更直观的图表来展示:

可以看到:

  1. 在线程数比较少的时候(不高于24个,即总CPU数目的一半),数据表的个数对整体的性能影响很小;当线程数较多时才显示出区别:相同线程数下,增加表数目可提升数据库整体吞吐量;
  2. InnoDB整体性能在48线程时达到顶峰,也即达到CPU的总数目,说明InnoDB能充分利用硬件多CPU的特性;
  3. 在线程数或者表数量很小的时候,增加线程数或者表数量可以线性地提升性能,在实际环境中值得注意;而在线程数量超过物理CPU数量时,整体插入性能会下降。

2、InnoDB & 异步刷新日志

innodb_flush_log_at_trx_commit设置为2,sync_binlog设置为 0,日志文件会每秒刷写一次到硬盘,并且不主动同步binlog的写入,而依赖于操作系统本身不定期把文件内容flush到硬盘。测试的情况见下表:

表数/插入TPS/线程数

1

2

4

8

12

16

1

7751.83

7776.78

7741.86

7739.29

7770.41

7662.18

2

15199.98

14952.94

15252.04

15184.54

15186.76

15176.68

4

29075.83

29194.62

29228.09

29204.63

29625.60

29406.31

8

53578.10

51007.42

53116.44

54029.60

53291.41

52173.69

16

61002.65

71383.45

74656.36

75597.66

76305.24

76412.77

24

52758.54

70906.04

78472.49

81999.99

80430.52

82896.78

32

51740.38

68061.25

79936.12

82063.79

84966.86

83667.26

48

50961.62

65962.79

79952.45

85511.97

86223.38

86718.83

64

53378.76

65758.29

74224.26

76779.63

75368.30

76614.14

80

55056.88

66799.11

73969.11

62867.60

62039.68

63572.61

用更直观的图表来展示:

可以看到与InnoDB Sync的情况有所不同:

  1. 异步的情况,随着线程数的增加,插入性能提升较快,在16个线程的时候已经接近峰值;
  2. 插入TPS的峰值比同步情况的峰值低,这个与以往SATA/SAS磁盘环境下的MySQL优化经验不匹配;通过iostat查看SSD盘的使用率很低,只有百分之几,因而SSD硬盘条件下的InnoDB的优化策略需要持续改进。

3、TokuDB & 同步刷新日志

tokudb_commit_sync设置为1,tokudb_fsync_log_period设置为0,也就是每次事务提交时,log buffer 会被写入到日志文件并刷写到硬盘。

表数/插入TPS/线程数

1

2

4

8

12

16

1

6506.16

6533.51

6514.36

6505.52

6581.28

6588.60

2

12335.72

12323.07

12494.74

12572.37

12600.94

12623.45

4

22726.24

23001.47

23331.96

23854.47

24267.20

24060.65

8

34935.53

38952.86

40093.37

41687.61

42472.60

44021.98

16

30777.25

42145.63

50293.47

55585.24

58956.65

59804.16

24

28102.26

38306.27

44420.44

47960.77

50440.59

52436.36

32

26227.49

35677.10

39627.22

40717.32

42562.45

44657.12

48

23335.33

30574.98

34961.22

34289.79

34819.25

35367.41

64

28923.69

36267.50

35228.70

35306.85

30393.76

29644.79

80

28323.74

33808.39

34203.47

35249.88

27757.45

32269.39

用图表来展示:

可以看到:

  1. 出乎意料的是,TokuDB在线程数16的时候插入TPS达到峰值,也就是说TokuDB并没有完全利用起多物理CPU的优势。
  2. 对比InnoDB线程数从1~16的情况可以看到,TokuDB在相同条件下比InnoDB的性能还要高;而在线程数增多的时候,TokuDB的插入TPS在逐渐减小,而InnoDB在线程数超过物理CPU个数的时,插入TPS才开始下降,说明TokuDB还有很大的优化空间。

4、TokuDB & 异步刷新日志

线程数/插入TPS/表数

1

2

4

8

12

16

1

6478.74

6514.03

6571.31

6555.92

6462.55

6588.75

2

12388.24

12433.75

12417.53

12457.83

12629.21

12597.90

4

22915.61

22265.08

24002.63

24248.57

22596.18

24323.07

8

35078.08

39179.46

39583.82

39505.79

42549.19

43493.89

16

30017.06

42012.43

46019.37

58790.76

60294.11

61057.96

24

27675.70

37873.94

45151.54

45075.48

49145.73

52417.81

32

26078.90

35496.19

39891.16

38888.13

43570.03

44882.92

48

23340.20

32392.89

35164.66

33858.16

34209.27

35350.72

64

29522.80

36475.76

36969.68

32381.53

32160.18

32589.76

80

27976.86

33483.40

34994.01

34977.62

30259.96

32680.34

用图表来展示:

对比之前的图标,可以看到:

  1. 与InnoDB不同的是,是否开启log的同步对TokuDB的插入性能影响不大,TokuDB SyncTokuDB Async两者的图形形状几乎一样。
  2. 与同步的情况类似,TokuDB在线程数16的时候插入TPS就达到峰值,有很大的优化空间。

5、压缩算法选择

压缩算法测试使用的实际的运行数据做测试,原来用InnoDB存储的日志数据为92GB,用mysqldump工具导出后为79GB。测试表是典型的日志存储表,其结构如下:

+-------+--------------+------+-----+---------+----------------+
| Field | Type         | Null | Key | Default | Extra          |
+-------+--------------+------+-----+---------+----------------+
| a     | int(11)      | NO   | PRI | NULL    | auto_increment | 
| b     | bigint(20)   | NO   | MUL | 0       |                | 
| c     | varchar(30)  | NO   |     |         |                | 
| d     | varchar(20)  | NO   |     |         |                | 
| e     | varchar(30)  | NO   |     |         |                | 
| f     | text         | NO   |     | NULL    |                | 
| g     | varchar(300) | NO   |     |         |                | 
| h     | int(11)      | NO   |     | 0       |                | 
| i     | int(11)      | NO   |     | 0       |                | 
| j     | int(11)      | NO   |     | 0       |                | 
| k     | int(11)      | NO   |     | 0       |                | 
+-------+--------------+------+-----+---------+----------------+

依次将TokuDB的tokudb_row_format设置为不同的压缩算法,得到其导入后的实际存储空间以及导入时间,测试结果如下:

压缩算法/项目

存储大小

导入时间

snappy

12GB

47min40s

quicklz

7.1GB

47min21s

zlib

5.7GB

48min9s

lzma

4.7GB

47min10s

从表中可以观察到:

  1. 几种压缩算法耗时差不多,相差很小;
  2. 不同的压缩算法的压缩比差异较大,snappy压缩比较小,约为6.6倍;压缩比最大的lzma为16.8倍;
  3. zlib作为官方选择的默认压缩算法,在压缩比和CPU消耗上有较好的平衡,压缩比为13.8倍。

结合在测试过程中持续观察CPU的使用情况,lzma算法在运行过程中CPU使用率在600%~700%左右,而zlib算法CPU使用率在80%~180%之间摆动。因而,在实际生产环境中,如果没有特殊的考虑,建议使用zlib压缩算法。

五、讨论与结论

本次测试以InnoDB为参考,主要测试TokuDB的写入性能以及存储压缩比。通过不同场景下的对比测试,可以得出几个观点:

  1. InnoDB现阶段插入性能有优势,性能大约高出30%左右;
  2. TokuDB虽然没有充分利用硬件的能力,但是已经表现出强大的足够高的性能,考虑到TokuDB的成熟度,后面它还有较大的提升空间,可以持续关注其后续进展;
  3. TokuDB选择日志同步或者异步刷新对性能影响不大,建议默认选择同步日志保护数据;
  4. TokuDB在数据压缩存储上有绝对的优势,十几倍的压缩比对于冷备数据存储有着极大的吸引力。

值得一提的是,InnoDB性能表现优异部分原因可归功于InnoDB的成熟度,可灵活的配置许多参数以适应特定的应用场景,而TokuDB暴露出的优化参数很少,不能根据硬件配置调整一些重要参数。综上,虽然TokuDB在现阶段还没成熟,但已经表现出强大的性能以及突出的特性,应该作为某些特定应用场景的首选。

原创声明,本文系作者授权云+社区-专栏发表,未经许可,不得转载。

如有侵权,请联系 yunjia_community@tencent.com 删除。

编辑于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏IT笔记

JavaWeb项目架构之Kafka分布式日志队列

架构、分布式、日志队列,标题自己都看着唬人,其实就是一个日志收集的功能,只不过中间加了一个Kafka做消息队列罢了。

56710
来自专栏沃趣科技

ASM 翻译系列第十七弹:ASM Internal ASM Disk Directory

原作者:Bane Radulovic 译者: 郭旭瑞 审核: 魏兴华 DBGeeK社群联合出品 ASM Disk Directory 本篇文章讲述A...

4008
来自专栏Java架构解析

为什么开发人员必须要了解数据库锁?

锁在现实中的意义为:封闭的器物,以钥匙或暗码开启。在计算机中的锁一般用来管理对共享资源的并发访问,比如我们java同学熟悉的Lock,synchronized等...

180
来自专栏Java技术栈

MySQL 调优/优化的 101 个建议!

原文:http://www.monitis.com/blog/101-tips-to-mysql-tuning-and-optimization/ MySQL是...

3826
来自专栏IT笔记

JavaWeb项目架构之Kafka分布式日志队列

架构、分布式、日志队列,标题自己都看着唬人,其实就是一个日志收集的功能,只不过中间加了一个Kafka做消息队列罢了。 ? kafka介绍 Kafka是由Apac...

26911
来自专栏「3306 Pai」社区

关于MySQL 8.0的几个重点,都在这里

在MySQL8.0中重新设计了redo log,主要改进fsync,使得效率更高,减少锁,优化flush机制,不会频繁flush。同时,支持更高用户并发请求。

610
来自专栏杨建荣的学习笔记

海量数据迁移之通过rowid切分大表(r2笔记62天)

在之前的章节中,讨论过了通过 分区+并行等方式来进行超大的表的切分,通过这种方式能够极大的提高数据的平均分布,但是不是最完美的。 比如在数据量再提高几个层次,我...

2928
来自专栏智能大石头

每天4亿行SQLite订单大数据测试(源码)

SQLite单表4亿订单,大数据测试 SQLite作为嵌入式数据库的翘楚,广受欢迎! 新生命团队自2010年以来,投入大量精力对SQLite进行学习研究,成功应...

2706
来自专栏沃趣科技

Oracle 12c ASM专题|Flex Diskgroup相关概念

原文链接 https://martincarstenbach.wordpress.com/2017/07/11/12-2-new-feature-the-fle...

2747
来自专栏乐沙弥的世界

Percona XtraDB Cluster 的一些使用限制(PXC 5.7)

Percona XtraDB Cluster有众多的优秀特性,使得mysql集群得以轻松实现。但是不要忽略了它的一些限制。如果你无法接受,或者你的应用程序或数据...

773

扫码关注云+社区