TokuDB做爲MySQL的大數據(Big Data)存儲引擎受到人們的廣泛關注。TokuDB擁有很高的壓縮比(官方稱最大可達25倍),能夠在很大的數據上建立大量的索引,並保持性能不降低。咱們來實測一下其真實性能如何?
做者:吳雙橋 騰訊雲數據庫工程師
出處:騰雲閣文章
----------------------------------------------------html
一 、背景介紹
近年來,TokuDB做爲MySQL的大數據(Big Data)存儲引擎受到人們的廣泛關注。其架構的核心基於一種新的叫作分形樹(Fractal Trees)的索引數據結構,該結構是緩存無關的,即便索引數據大小超過內存性能也不會降低,也即沒有內存生命週期和碎片的問題。mysql
特別引人注意的是,TokuDB擁有很高的壓縮比(官方稱最大可達25倍),能夠在很大的數據上建立大量的索引,並保持性能不降低。同時,TokuDB支持ACID和MVCC,還有在線修改表結構(Live Schema Modification)以及增長的複製性能等特性,使其在某些特定的應用領域(如日誌存儲與分析)有着獨特的優點。ios
在TokuDB的應用場景中,一般是數據庫插入操做的量遠遠大於讀取的量,於是本此測試主要針對TokuDB的插入性能以及壓縮比,以InnoDB做爲參考基準。算法
2、測試環境搭建
測試使用的機器爲高配機型,內存大於100G,CPU型號爲Intel(R) Xeon(R) CPU E5系列,數據盤使用的是SSD硬盤。sql
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引擎已經就緒,並被設置爲了默認的存儲引擎。緩存
3、測試工具與變量
一、測試工具選擇
如今開源可用的MySQL基準測試工具備不少,如mysqlslap,MySQL Benchmark Suite,Super Smack,Database Test Suite,TPCC和sysbench等。綜合工具的功能、易用性還有流行程度,最終選定操做簡單但功能強大的sysbench做爲測試工具。在sysbench 0.5版本中,已經開始支持Lua腳本,使用修改起來很是靈活。另外,測試壓縮比直接使用的mysqldump工具。安全
二、測試變量
插入性能相關的變量
除去根據機器硬件特性配置的常規優化參數,對於存儲引擎插入性能影響最大的是:是否將事務和binlog同步刷新到硬盤。微信
須要特別說明的是,還有一個比較重要的指標,便是否開啓了DIRECT IO功能,因爲在測試環境InnoDB開啓了DIRECT IO,並能提升總體的性能,而TokuDB在測試機型上沒法開啓DIRECT IO功能,因此在這點上InnoDB有相對的優點。數據結構
InnoDB 相關
對於InnoDB來講,控制這個功能的參數爲innodb_flush_log_at_trx_commit
和sync_binlog
。
innodb_flush_log_at_trx_commit
參數指定了InnoDB在事務提交後的日誌寫入頻率。具體來講:
- 當
innodb_flush_log_at_trx_commit
取值爲 0 時,log buffer 會 每秒寫入到日誌文件並刷寫(flush)到硬盤。但每次事務提交不會有任何影響,也就是 log buffer 的刷寫操做和事務提交操做沒有關係。在這種狀況下,MySQL性能最好,但若是 mysqld 進程崩潰,一般會致使最後 1s 的日誌丟失。 - 當取值爲 1 時,每次事務提交時,log buffer 會被寫入到日誌文件並刷寫到硬盤。這也是默認值。這是最安全的配置,但因爲每次事務都須要進行硬盤I/O,因此也最慢。
- 當取值爲 2 時,每次事務提交會寫入日誌文件,但並不會當即刷寫到硬盤,日誌文件會每秒刷寫一次到硬盤。這時若是 mysqld 進程崩潰,因爲日誌已經寫入到系統緩存,因此並不會丟失數據;在操做系統崩潰的狀況下,一般會致使最後 1s 的日誌丟失。
在實際的生產系統中,innodb_flush_log_at_trx_commit
會在1和2之間選擇。通常來講,對數據一致性和完整性要求比較高的應用場景,會將其值設置爲1。
sync_binlog
參數指定了 MySQL 的二進制日誌同步到硬盤的頻率。若是MySQL autocommit開啓,那麼每一個語句都寫一次binlog,不然每次事務寫一次。
- 默認值爲 0,不主動同步binlog的寫入,而依賴於操做系統自己不按期把文件內容flush到硬盤。
- 設置爲 1 時,在每一個語句或者事務後會同步一次binlog,即便發生意外崩潰時也最多丟失一個事務的日誌,於是速度較慢。
一般狀況下,innodb_flush_log_at_trx_commit
和sync_binlog
配合起來使用,本次性能測試覆蓋了同步刷新日誌和異步刷新日誌兩種策略。
TokuDB 相關
TokuDB中與InnoDB相似的指標爲tokudb_commit_sync
和tokudb_fsync_log_period
。與innodb_flush_log_at_trx_commit
的含義相似,tokudb_commit_sync
指定當事務提交的時候,是否要刷新日誌到硬盤上。
- 默認開啓,值爲1。也就是每次事務提交時,log buffer 會被寫入到日誌文件並刷寫到硬盤。
- 若是設置爲 0,每次事務提交會寫入日誌文件,但並不會當即刷寫到硬盤,日誌文件會每隔一段時間刷寫一次到硬盤。這個時間間隔由
tokudb_commit_sync
指定。
tokudb_fsync_log_period
指定多久將日誌文件刷新到硬盤,TukuDB的log buffer總大小爲 32 MB且不可更改。默認爲 0 秒,此時若是tokudb_commit_sync
設置爲開啓,那麼這個值默認爲 1 分鐘。
tokudb_commit_sync
和tokudb_fsync_log_period
一般也是配合起來使用,本次性能測試覆蓋了兩種典型的組合策略。
壓縮比相關的變量
大多數選擇使用TokuDB的場景,都很是重視它的存儲壓縮比,於是在實際應用場景中總會配套使用某種壓縮算法。當前TokuDB支持的壓縮算法有,quicklz, zlib, lzma, snappy,固然還有不壓縮uncompressed。關於壓縮算法的討論,能夠參考官方博客的一篇分析文章。
本次測試會結合真實的數據來從壓縮比、耗時兩個方面來檢驗上面幾個不一樣的壓縮算法。TokuDB能夠經過在配置文件中設置tokudb_row_format
來指定不一樣的壓縮算法,它們的取值分別是:TOKUDB_QUICKLZ
, TOKUDB_ZLIB
, TOKUDB_LZMA
和TOKUDB_SNAPPY
。值得注意的是,zlib算法是TokuDB官方最新版本的默認算法,也是現今支持TokuDB的雲服務商的默認推薦算法。
sysbench壓縮工具相關的變量
sysbench針對mysql壓測的參數有不少,這裏選取的是與實際應用場景最爲相關的兩個參數:表數量以及線程數量。表數量對應的是數據庫實際在同時寫入的表的數量,線程數對應的到MySQL數據庫上的鏈接。其餘的參數,如表的大小,是不是事務等可能影響總體的插入性能,但影響並不顯著,這裏只選取最主要的兩個參數進行分析。
三、測試方法
本測試的採用的方式爲經典的控制變量法。這裏的變量有:採用的存儲引擎類型,是否同步刷新日誌,採用的壓縮算法,以及另外兩個與sysbench相關的參數:壓測的線程數量和壓測的表數量。其中,壓縮算法的選擇只是在四種算法中選擇一種,因此並不與其餘變量交叉測試。這樣以存儲引擎和同步刷新日誌來劃分測試,能夠將整個測試數據分爲四個大類:
- InnoDB & 同步刷新日誌
- InnoDB & 異步刷新日誌
- TokuDB & 同步刷新日誌
- TokuDB & 異步刷新日誌
在每一個大類下,對壓測線程數量和壓測表數量進行交叉測試。壓測表數量取值可能爲[1, 2, 4, 8, 12, 16],線程數的可能取值爲[1, 2, 4, 8, 16, 24, 32, 48, 64, 80],於是每一個大類下進行6 * 10 = 60 次壓測,每次壓測寫入2,000,000 條數據,對每次壓測進行插入性能統計。
4、測試結果分析
一、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 |
用更直觀的圖表來展現:
能夠看到:
- 在線程數比較少的時候(不高於24個,即總CPU數目的一半),數據表的個數對總體的性能影響很小;當線程數較多時才顯示出區別:相同線程數下,增長表數目可提高數據庫總體吞吐量
- InnoDB總體性能在48線程時達到頂峯,也即達到CPU的總數目,說明InnoDB能充分利用硬件多CPU的特性
- 在線程數或者表數量很小的時候,增長線程數或者表數量能夠線性地提高性能,在實際環境中值得注意;而在線程數量超過物理CPU數量時,總體插入性能會降低
二、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
的狀況有所不一樣:
- 異步的狀況,隨着線程數的增長,插入性能提高較快,在16個線程的時候已經接近峯值
- 插入TPS的峯值比同步狀況的峯值低,這個與以往SATA/SAS磁盤環境下的MySQL優化經驗不匹配;經過iostat查看SSD盤的使用率很低,只有百分之幾,於是SSD硬盤條件下的InnoDB的優化策略須要持續改進
三、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 |
用圖表來展現:
能夠看到:
- 出乎意料的是,TokuDB在線程數16的時候插入TPS達到峯值,也就是說TokuDB並無徹底利用起多物理CPU的優點
- 對比InnoDB線程數從1~16的狀況能夠看到,TokuDB在相同條件下比InnoDB的性能還要高;而在線程數增多的時候,TokuDB的插入TPS在逐漸減少,而InnoDB在線程數超過物理CPU個數的時,插入TPS纔開始降低,說明TokuDB還有很大的優化空間
四、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 |
用圖表來展現:
對比以前的圖標,能夠看到:
- 與InnoDB不一樣的是,是否開啓log的同步對TokuDB的插入性能影響不大,
TokuDB Sync
和TokuDB Async
二者的圖形形狀幾乎同樣 - 與同步的狀況相似,TokuDB在線程數16的時候插入TPS就達到峯值,有很大的優化空間
五、壓縮算法選擇
壓縮算法測試使用的實際的運行數據作測試,原來用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 |
從表中能夠觀察到:
- 幾種壓縮算法耗時差很少,相差很小
- 不一樣的壓縮算法的壓縮比差別較大,snappy壓縮比較小,約爲6.6倍;壓縮比最大的lzma爲16.8倍
- zlib做爲官方選擇的默認壓縮算法,在壓縮比和CPU消耗上有較好的平衡,壓縮比爲13.8倍
結合在測試過程當中持續觀察CPU的使用狀況,lzma算法在運行過程當中CPU使用率在600%~700%左右,而zlib算法CPU使用率在80%~180%之間擺動。於是,在實際生產環境中,若是沒有特殊的考慮,建議使用zlib壓縮算法。
5、討論與結論
本次測試以InnoDB爲參考,主要測試TokuDB的寫入性能以及存儲壓縮比。經過不一樣場景下的對比測試,能夠得出幾個觀點:
- InnoDB現階段插入性能有優點,性能大約高出30%左右
- TokuDB雖然沒有充分利用硬件的能力,可是已經表現出強大的足夠高的性能,考慮到TokuDB的成熟度,後面它還有較大的提高空間,能夠持續關注其後續進展
- TokuDB選擇日誌同步或者異步刷新對性能影響不大,建議默認選擇同步日誌保護數據
- TokuDB在數據壓縮存儲上有絕對的優點,十幾倍的壓縮比對於冷備數據存儲有着極大的吸引力
值得一提的是,InnoDB性能表現優異部分緣由可歸功於InnoDB的成熟度,可靈活的配置許多參數以適應特定的應用場景,而TokuDB暴露出的優化參數不多,不能根據硬件配置調整一些重要參數。綜上,雖然TokuDB在現階段還沒成熟,但已經表現出強大的性能以及突出的特性,應該做爲某些特定應用場景的首選。
------------------------------
獲取更多雲計算技術乾貨,可請前往騰訊雲技術社區
微信公衆號:騰訊雲技術社區( QcloudCommunity)