TokuDB作為MySQL的大數(shù)據(jù)(Big Data)存儲(chǔ)引擎受到人們的普遍關(guān)注。TokuDB擁有很高的壓縮比(官方稱最大可達(dá)25倍),可以在很大的數(shù)據(jù)上創(chuàng)建大量的索引,并保持性能不下降。我們來實(shí)測(cè)一下其真實(shí)性能如何?
作者:吳雙橋 ? ? ?騰訊云數(shù)據(jù)庫工程師
出處:騰云閣文章
---------------------------------------------------
一 、背景介紹
近年來,TokuDB作為MySQL的大數(shù)據(jù)(Big Data)存儲(chǔ)引擎受到人們的普遍關(guān)注。其架構(gòu)的核心基于一種新的叫做分形樹(Fractal Trees)的索引數(shù)據(jù)結(jié)構(gòu),該結(jié)構(gòu)是緩存無關(guān)的,即使索引數(shù)據(jù)大小超過內(nèi)存性能也不會(huì)下降,也即沒有內(nèi)存生命周期和碎片的問題。
特別引人注意的是,TokuDB擁有很高的壓縮比(官方稱最大可達(dá)25倍),可以在很大的數(shù)據(jù)上創(chuàng)建大量的索引,并保持性能不下降。同時(shí),TokuDB支持ACID和MVCC,還有在線修改表結(jié)構(gòu)(Live Schema Modification)以及增加的復(fù)制性能等特性,使其在某些特定的應(yīng)用領(lǐng)域(如日志存儲(chǔ)與分析)有著獨(dú)特的優(yōu)勢(shì)。
在TokuDB的應(yīng)用場景中,通常是數(shù)據(jù)庫插入操作的量遠(yuǎn)遠(yuǎn)大于讀取的量,因而本此測(cè)試主要針對(duì)TokuDB的插入性能以及壓縮比,以InnoDB作為參考基準(zhǔn)。
二、測(cè)試環(huán)境搭建
測(cè)試使用的機(jī)器為高配機(jī)型,內(nèi)存大于100G,CPU型號(hào)為Intel(R) Xeon(R) CPU E5系列,數(shù)據(jù)盤使用的是SSD硬盤。
MySQL TokuDB版本使用的是 5.6.28-76.1,按照Percona網(wǎng)站上的安裝方法使用插件的方式進(jìn)行安裝,見官網(wǎng)教程。使用MySQL命令查看:

可以看到TokuDB引擎已經(jīng)就緒,并被設(shè)置為了默認(rèn)的存儲(chǔ)引擎。
三、測(cè)試工具與變量
1、測(cè)試工具選擇
現(xiàn)在開源可用的MySQL基準(zhǔn)測(cè)試工具有很多,如mysqlslap,MySQL Benchmark Suite,Super Smack,Database Test Suite,TPCC和sysbench等。綜合工具的功能、易用性還有流行程度,最終選定操作簡單但功能強(qiáng)大的sysbench作為測(cè)試工具。在sysbench 0.5版本中,已經(jīng)開始支持Lua腳本,使用修改起來非常靈活。另外,測(cè)試壓縮比直接使用的mysqldump工具。
2、測(cè)試變量
插入性能相關(guān)的變量
除去根據(jù)機(jī)器硬件特性配置的常規(guī)優(yōu)化參數(shù),對(duì)于存儲(chǔ)引擎插入性能影響最大的是:是否將事務(wù)和binlog同步刷新到硬盤。
需要特別說明的是,還有一個(gè)比較重要的指標(biāo),即是否開啟了DIRECT IO功能,由于在測(cè)試環(huán)境InnoDB開啟了DIRECT IO,并能提高整體的性能,而TokuDB在測(cè)試機(jī)型上無法開啟DIRECT IO功能,所以在這點(diǎn)上InnoDB有相對(duì)的優(yōu)勢(shì)。
InnoDB 相關(guān)
對(duì)于InnoDB來說,控制這個(gè)功能的參數(shù)為innodb_flush_log_at_trx_commit和sync_binlog。
innodb_flush_log_at_trx_commit參數(shù)指定了InnoDB在事務(wù)提交后的日志寫入頻率。具體來說:
當(dāng)innodb_flush_log_at_trx_commit取值為 0 時(shí),log buffer 會(huì) 每秒寫入到日志文件并刷寫(flush)到硬盤。但每次事務(wù)提交不會(huì)有任何影響,也就是 log buffer 的刷寫操作和事務(wù)提交操作沒有關(guān)系。在這種情況下,MySQL性能最好,但如果 mysqld 進(jìn)程崩潰,通常會(huì)導(dǎo)致最后 1s 的日志丟失。
當(dāng)取值為 1 時(shí),每次事務(wù)提交時(shí),log buffer 會(huì)被寫入到日志文件并刷寫到硬盤。這也是默認(rèn)值。這是最安全的配置,但由于每次事務(wù)都需要進(jìn)行硬盤I/O,所以也最慢。
當(dāng)取值為 2 時(shí),每次事務(wù)提交會(huì)寫入日志文件,但并不會(huì)立即刷寫到硬盤,日志文件會(huì)每秒刷寫一次到硬盤。這時(shí)如果 mysqld 進(jìn)程崩潰,由于日志已經(jīng)寫入到系統(tǒng)緩存,所以并不會(huì)丟失數(shù)據(jù);在操作系統(tǒng)崩潰的情況下,通常會(huì)導(dǎo)致最后 1s 的日志丟失。
在實(shí)際的生產(chǎn)系統(tǒng)中,innodb_flush_log_at_trx_commit會(huì)在1和2之間選擇。一般來說,對(duì)數(shù)據(jù)一致性和完整性要求比較高的應(yīng)用場景,會(huì)將其值設(shè)置為1。
sync_binlog參數(shù)指定了 MySQL 的二進(jìn)制日志同步到硬盤的頻率。如果MySQL autocommit開啟,那么每個(gè)語句都寫一次binlog,否則每次事務(wù)寫一次。
默認(rèn)值為 0,不主動(dòng)同步binlog的寫入,而依賴于操作系統(tǒng)本身不定期把文件內(nèi)容flush到硬盤。
設(shè)置為 1 時(shí),在每個(gè)語句或者事務(wù)后會(huì)同步一次binlog,即使發(fā)生意外崩潰時(shí)也最多丟失一個(gè)事務(wù)的日志,因而速度較慢。
通常情況下,innodb_flush_log_at_trx_commit和sync_binlog配合起來使用,本次性能測(cè)試覆蓋了同步刷新日志和異步刷新日志兩種策略。
TokuDB 相關(guān)
TokuDB中與InnoDB類似的指標(biāo)為tokudb_commit_sync和tokudb_fsync_log_period。與innodb_flush_log_at_trx_commit的含義類似,tokudb_commit_sync指定當(dāng)事務(wù)提交的時(shí)候,是否要刷新日志到硬盤上。
默認(rèn)開啟,值為1。也就是每次事務(wù)提交時(shí),log buffer 會(huì)被寫入到日志文件并刷寫到硬盤。
如果設(shè)置為 0,每次事務(wù)提交會(huì)寫入日志文件,但并不會(huì)立即刷寫到硬盤,日志文件會(huì)每隔一段時(shí)間刷寫一次到硬盤。這個(gè)時(shí)間間隔由tokudb_commit_sync指定。
tokudb_fsync_log_period指定多久將日志文件刷新到硬盤,TukuDB的log buffer總大小為 32 MB且不可更改。默認(rèn)為 0 秒,此時(shí)如果tokudb_commit_sync設(shè)置為開啟,那么這個(gè)值默認(rèn)為 1 分鐘。
tokudb_commit_sync和tokudb_fsync_log_period通常也是配合起來使用,本次性能測(cè)試覆蓋了兩種典型的組合策略。
壓縮比相關(guān)的變量
大多數(shù)選擇使用TokuDB的場景,都非常重視它的存儲(chǔ)壓縮比,因而在實(shí)際應(yīng)用場景中總會(huì)配套使用某種壓縮算法。當(dāng)前TokuDB支持的壓縮算法有,quicklz, zlib, lzma, snappy,當(dāng)然還有不壓縮uncompressed。關(guān)于壓縮算法的討論,可以參考官方博客的一篇分析文章。
本次測(cè)試會(huì)結(jié)合真實(shí)的數(shù)據(jù)來從壓縮比、耗時(shí)兩個(gè)方面來檢驗(yàn)上面幾個(gè)不同的壓縮算法。TokuDB可以通過在配置文件中設(shè)置tokudb_row_format來指定不同的壓縮算法,它們的取值分別是:TOKUDB_QUICKLZ,TOKUDB_ZLIB,TOKUDB_LZMA和TOKUDB_SNAPPY。值得注意的是,zlib算法是TokuDB官方最新版本的默認(rèn)算法,也是現(xiàn)今支持TokuDB的云服務(wù)商的默認(rèn)推薦算法。
sysbench壓縮工具相關(guān)的變量
sysbench針對(duì)mysql壓測(cè)的參數(shù)有很多,這里選取的是與實(shí)際應(yīng)用場景最為相關(guān)的兩個(gè)參數(shù):表數(shù)量以及線程數(shù)量。表數(shù)量對(duì)應(yīng)的是數(shù)據(jù)庫實(shí)際在同時(shí)寫入的表的數(shù)量,線程數(shù)對(duì)應(yīng)的到MySQL數(shù)據(jù)庫上的連接。其他的參數(shù),如表的大小,是否是事務(wù)等可能影響整體的插入性能,但影響并不顯著,這里只選取最主要的兩個(gè)參數(shù)進(jìn)行分析。
3、測(cè)試方法
本測(cè)試的采用的方式為經(jīng)典的控制變量法。這里的變量有:采用的存儲(chǔ)引擎類型,是否同步刷新日志,采用的壓縮算法,以及另外兩個(gè)與sysbench相關(guān)的參數(shù):壓測(cè)的線程數(shù)量和壓測(cè)的表數(shù)量。其中,壓縮算法的選擇只是在四種算法中選擇一種,所以并不與其他變量交叉測(cè)試。這樣以存儲(chǔ)引擎和同步刷新日志來劃分測(cè)試,可以將整個(gè)測(cè)試數(shù)據(jù)分為四個(gè)大類:
InnoDB & 同步刷新日志
InnoDB & 異步刷新日志
TokuDB & 同步刷新日志
TokuDB & 異步刷新日志
在每個(gè)大類下,對(duì)壓測(cè)線程數(shù)量和壓測(cè)表數(shù)量進(jìn)行交叉測(cè)試。壓測(cè)表數(shù)量取值可能為[1, 2, 4, 8, 12, 16],線程數(shù)的可能取值為[1, 2, 4, 8, 16, 24, 32, 48, 64, 80],因而每個(gè)大類下進(jìn)行6 * 10 = 60 次壓測(cè),每次壓測(cè)寫入2,000,000 條數(shù)據(jù),對(duì)每次壓測(cè)進(jìn)行插入性能統(tǒng)計(jì)。
四、測(cè)試結(jié)果分析
1、InnoDB & 同步刷新日志
將innodb_flush_log_at_trx_commit設(shè)置為1,sync_binlog設(shè)置為1,也即是保證數(shù)據(jù)最安全:同步刷新log到硬盤,并且針對(duì)每個(gè)事務(wù)同步一次binlog。測(cè)試的情況見下:

用更直觀的圖表來展示:

可以看到:
在線程數(shù)比較少的時(shí)候(不高于24個(gè),即總CPU數(shù)目的一半),數(shù)據(jù)表的個(gè)數(shù)對(duì)整體的性能影響很??;當(dāng)線程數(shù)較多時(shí)才顯示出區(qū)別:相同線程數(shù)下,增加表數(shù)目可提升數(shù)據(jù)庫整體吞吐量
InnoDB整體性能在48線程時(shí)達(dá)到頂峰,也即達(dá)到CPU的總數(shù)目,說明InnoDB能充分利用硬件多CPU的特性
在線程數(shù)或者表數(shù)量很小的時(shí)候,增加線程數(shù)或者表數(shù)量可以線性地提升性能,在實(shí)際環(huán)境中值得注意;而在線程數(shù)量超過物理CPU數(shù)量時(shí),整體插入性能會(huì)下降
2、InnoDB & 異步刷新日志
將innodb_flush_log_at_trx_commit設(shè)置為2,sync_binlog設(shè)置為 0,日志文件會(huì)每秒刷寫一次到硬盤,并且不主動(dòng)同步binlog的寫入,而依賴于操作系統(tǒng)本身不定期把文件內(nèi)容flush到硬盤。測(cè)試的情況見下表:

用更直觀的圖表來展示:

可以看到與InnoDB Sync的情況有所不同:
異步的情況,隨著線程數(shù)的增加,插入性能提升較快,在16個(gè)線程的時(shí)候已經(jīng)接近峰值
插入TPS的峰值比同步情況的峰值低,這個(gè)與以往SATA/SAS磁盤環(huán)境下的MySQL優(yōu)化經(jīng)驗(yàn)不匹配;通過iostat查看SSD盤的使用率很低,只有百分之幾,因而SSD硬盤條件下的InnoDB的優(yōu)化策略需要持續(xù)改進(jìn)
3、TokuDB & 同步刷新日志
將tokudb_commit_sync設(shè)置為1,tokudb_fsync_log_period設(shè)置為0,也就是每次事務(wù)提交時(shí),log buffer 會(huì)被寫入到日志文件并刷寫到硬盤。

用圖表來展示:

可以看到:
出乎意料的是,TokuDB在線程數(shù)16的時(shí)候插入TPS達(dá)到峰值,也就是說TokuDB并沒有完全利用起多物理CPU的優(yōu)勢(shì)
對(duì)比InnoDB線程數(shù)從1~16的情況可以看到,TokuDB在相同條件下比InnoDB的性能還要高;而在線程數(shù)增多的時(shí)候,TokuDB的插入TPS在逐漸減小,而InnoDB在線程數(shù)超過物理CPU個(gè)數(shù)的時(shí),插入TPS才開始下降,說明TokuDB還有很大的優(yōu)化空間
4、TokuDB & 異步刷新日志
線程數(shù)/插入TPS/表數(shù)12481216

用圖表來展示:

對(duì)比之前的圖標(biāo),可以看到:
與InnoDB不同的是,是否開啟log的同步對(duì)TokuDB的插入性能影響不大,TokuDB Sync和TokuDB Async兩者的圖形形狀幾乎一樣
與同步的情況類似,TokuDB在線程數(shù)16的時(shí)候插入TPS就達(dá)到峰值,有很大的優(yōu)化空間
5、壓縮算法選擇
壓縮算法測(cè)試使用的實(shí)際的運(yùn)行數(shù)據(jù)做測(cè)試,原來用InnoDB存儲(chǔ)的日志數(shù)據(jù)為92GB,用mysqldump工具導(dǎo)出后為79GB。測(cè)試表是典型的日志存儲(chǔ)表,其結(jié)構(gòu)如下:

依次將TokuDB的tokudb_row_format設(shè)置為不同的壓縮算法,得到其導(dǎo)入后的實(shí)際存儲(chǔ)空間以及導(dǎo)入時(shí)間,測(cè)試結(jié)果如下:

從表中可以觀察到:
幾種壓縮算法耗時(shí)差不多,相差很小
不同的壓縮算法的壓縮比差異較大,snappy壓縮比較小,約為6.6倍;壓縮比最大的lzma為16.8倍
zlib作為官方選擇的默認(rèn)壓縮算法,在壓縮比和CPU消耗上有較好的平衡,壓縮比為13.8倍
結(jié)合在測(cè)試過程中持續(xù)觀察CPU的使用情況,lzma算法在運(yùn)行過程中CPU使用率在600%~700%左右,而zlib算法CPU使用率在80%~180%之間擺動(dòng)。因而,在實(shí)際生產(chǎn)環(huán)境中,如果沒有特殊的考慮,建議使用zlib壓縮算法。
五、討論與結(jié)論
本次測(cè)試以InnoDB為參考,主要測(cè)試TokuDB的寫入性能以及存儲(chǔ)壓縮比。通過不同場景下的對(duì)比測(cè)試,可以得出幾個(gè)觀點(diǎn):
InnoDB現(xiàn)階段插入性能有優(yōu)勢(shì),性能大約高出30%左右
TokuDB雖然沒有充分利用硬件的能力,但是已經(jīng)表現(xiàn)出強(qiáng)大的足夠高的性能,考慮到TokuDB的成熟度,后面它還有較大的提升空間,可以持續(xù)關(guān)注其后續(xù)進(jìn)展
TokuDB選擇日志同步或者異步刷新對(duì)性能影響不大,建議默認(rèn)選擇同步日志保護(hù)數(shù)據(jù)
TokuDB在數(shù)據(jù)壓縮存儲(chǔ)上有絕對(duì)的優(yōu)勢(shì),十幾倍的壓縮比對(duì)于冷備數(shù)據(jù)存儲(chǔ)有著極大的吸引力
值得一提的是,InnoDB性能表現(xiàn)優(yōu)異部分原因可歸功于InnoDB的成熟度,可靈活的配置許多參數(shù)以適應(yīng)特定的應(yīng)用場景,而TokuDB暴露出的優(yōu)化參數(shù)很少,不能根據(jù)硬件配置調(diào)整一些重要參數(shù)。綜上,雖然TokuDB在現(xiàn)階段還沒成熟,但已經(jīng)表現(xiàn)出強(qiáng)大的性能以及突出的特性,應(yīng)該作為某些特定應(yīng)用場景的首選。
------------------------------------------------------------------------------------------
獲取更多云計(jì)算技術(shù)干貨,可請(qǐng)前往?騰訊云技術(shù)社區(qū)
我也會(huì)持續(xù)同步更新~
微信公眾號(hào):騰訊云技術(shù)社區(qū)( QcloudCommunity)
