MySQL Casual Talks Vol.8 でMySQL 5.7とMariaDB 10.1の性能比較について発表しました
はじめに
遅くなりましたが11/20(金)に開催されたMySQL Casual Talks Vol.8で以下スライドで発表しました。その内容の補足とかを載せておきます。
最近MariaDB 10.1がGAになり、MySQL 5.7がGAになり、MariaDBってどうなん?、とか聞かれる事が増えたためとりあえずベンチマークで性能比較してみよう、が発端でした。MariaDBの10系はMySQL 5.5をベースにしているということで正直あまり期待していなかったのですが、起動時のログを見るとInnoDBはPerconaのXtraDB5.6ベースだったのでPercona5.6と同じ傾向かなぁという想像で実施しましたが概ね同じ傾向となりました。
まず、私はMariaDB10系はまともに触ったことがなかったので変だなと思った所を色々書いていきます。
MariaDBの変だと思った所
まずは1.の変なログです。
InnoDB: Warning: innodb_page_size has been changed from default value 16384 to 4096d. (###EXPERIMENTAL### operation) 2015-11-30 01:58:57 2ab81a63f2a0 InnoDB: innodb-page-size has been changed from the default value 16384 to 4096 (snip) 2015-11-30 1:59:03 46976268028224 [Warning] Failed to load slave replication state from table mysql.gtid_slave_pos: 1146: Table 'mysql.gtid_slave_pos' doesn't exist InnoDB: Note: File system for file ./mysql/innodb_table_stats.ibd has file block size 4096 not supported for page_size 4096 InnoDB: Note: Using file block size 2048 for file ./mysql/innodb_table_stats.ibd InnoDB: Note: File system for file ./mysql/innodb_index_stats.ibd has file block size 4096 not supported for page_size 4096 InnoDB: Note: Using file block size 2048 for file ./mysql/innodb_index_stats.ibd InnoDB: Note: File system for file ./mysql/gtid_slave_pos.ibd has file block size 4096 not supported for page_size 4096 InnoDB: Note: Using file block size 2048 for file ./mysql/gtid_slave_pos.ibd (snip)
一応これでも動くようですが凄く気持ち悪いです。少なくもとMySQL5.6, 5.7では出力されません。
ですので、今回発表の全てのベンチマークではデフォルトのinnodb_page_size=16384(16k)で実施しています。
続いて2.について。ディスクI/O状況のグラフです。左側がMySQL5.7、右側がMariaDB10.1となります。
MySQL5.7ではほぼほぼreadが発生しない状態になるのですが、MariaDBについては絶えず8〜9MB/secの読み取り(bio)が発生しています。pt-ioprofile等で見ましたが読み取り対象のファイルが分かりませんでした。dstat使うと間違いなくMariaDBのプロセスが読み取りを行っているのですが対象ファイルが完全に謎。知っている方がいましたら教えて下さい。
あと、MySQLとの互換性を頻繁に主張しているMariaDBですが、パラメータで見るとMySQL5.6にあったパラメータでもMariaDB10.1には存在しなかったりします。例えば以下のもの。
master_info_repository relay_log_info_repository
InnoDBはXtraDB5.6系なのでInnoDB関連パラメータは割りと同じのあるかむしろ多いかなのですがInnoDB以外の所は5.5系ベースのためこういった存在しないパラメータが出てくるのだと思います。SQLベースだったら互換性保たれてるんですかね?
sysbenchの補足
今回select.luaとoltp.luaを使っていますがやっていることはほぼほぼ一緒です。以下luaファイルの中身の抜粋です。
select.luaの抜粋 function event(thread_id) local table_name table_name = "sbtest".. sb_rand_uniform(1, oltp_tables_count) rs = db_query("SELECT pad FROM ".. table_name .." WHERE id=" .. sb_rand(1, oltp_table_size)) end oltp.luaの抜粋 for i=1, oltp_point_selects do rs = db_query("SELECT c FROM ".. table_name .." WHERE id=" .. sb_rand(1, oltp_table_size)) end
oltp.luaを見ると他にもクエリ発行する処理が書かれていますが今回実行したオプションでは上記のクエリのみの実行となります。Dimitriさんのブログ、MariaDBのブログではoltp.luaで実行してるようでしたので比較のために両方取った形になります。
oltp.luaは見たとおりforでぐるぐる回すので速くなったようです。
LinkBench実行についての補足
LinkBench実行前にmysqldプロセスを停止し、ファイルシステムキャッシュを開放しています。
echo 3 > /proc/sys/vm/drop_caches
ib_buffer_poolファイルも削除し、mysqld起動時のバッファの暖気は行わないようしています。
その他ベンチマーク時にはまった点
はまった点というかCentOSでは7系から採用されたsystemdに慣れていないせいではあるのですが、systemd経由で起動した場合、MySQL 5.7もMariaDB 10.1もmysqld_safeを経由しないため、これまでmysqld_safeで設定されていた項目を全てsystemdの起動設定ファイルに記載する必要があります。
今回行ったのは以下2点です。
- jemallocの使用
- numactlの使用
jemallocについて。mysqld_safeを経由する場合は [mysqld_safe]セクションにmalloc-lib=/lib64/libjemalloc.so.1のように書くことで指定出来たのですが、これを/etc/systemd/system/mysqld.service.d/service.conf等に書く必要があります。
またopen_files_limitパラメータについてもsystemdの起動設定ファイルにLimitNOFILEが記載されていて、LimitNOFILE以下に制限されてしまうので大きな値をopen_files_limitで指定している場合は変更する必要があります。以下記載例です。
[Service] LimitNOFILE=65535 Environment="LD_PRELOAD=/lib64/libjemalloc.so.1"
systemdを使う場合の設定については本家のマニュアル(2.5.10 Managing MySQL Server with systemd)を参照して下さい。
numactlについて。NUMA環境ではSwap Insanity予防のためnumactl --interleave=allで起動する事を個人的に推奨しており、おそらくその他の方も行っていると思います。
MySQL 5.6、5.7の最新版ではinnodb_numa_interleaveというパラメータが増えているのでこれを有効にすればnumactl --interleave=allで起動したのとほぼ同様の効果が得られるため本家のMySQLではnumactlはあまり必要では無くなっています(InnoDBバッファプールのみinterleave=allになる)。
mysqld_safeを経由していた場合、Perconaでは[mysqld_safe]セクションにnuma-interleave=1としておくとnumactl --interleave=allで起動したのと同様の事を内部的に行ってくれるのですが、先にも記載した通りsystemd経由の場合はmysqld_safeは使われません。
そのためMariaDBでは/usr/lib/systemd/system/mariadb.serviceを以下のように書き換えて起動していました。変更箇所のみ抜粋したのが以下です。
#ExecStart=/usr/sbin/mysqld $MYSQLD_OPTS ExecStart=/usr/bin/numactl --interleave=all /usr/sbin/mysqld $MYSQLD_OPTS
公開されているベンチマーク結果について
OracleやPercona、MariaDBが公開しているベンチマーク結果がありますが、細かいパラメータやサーバ環境が載っていないものについては話半分というかそういう事もあるんだね、という程度でしか見ていません。実際に同じようなベンチマークを行い、同じ傾向になれば少なくとも自分が取得したH/W環境において、公開されているベンチマークの傾向については信用しても良いな、と判断しています。
MariaDBのブログの公式としてのベンチマーク結果(と捉えて問題無いと思いますが)は、正直あまり信用していません。何故かというと環境に関する公開情報がほとんどのケースで少なすぎるからです。
ぶっちゃけ人の取ったベンチマークなんて鵜呑みにするもんじゃない、と思っています(私の公開しているのもその程度の見方でOKです。信用出来ると思った場合は信用して下さい)。基本疑って掛かって下さい(特にベンダーが対抗して出したようなやつ)。そもそもベンチマークツールで取得した結果・傾向がそのままそれぞれのサービス環境で同じ傾向になる事なんてマレだと思います。
それでもMySQL5.7のreadwrite時の性能改善については特筆すべきものがあると感じています。performance_schemaからの傾向と実際のベンチマークからもそう感じています。ちょっと上手く取れてなかったようですが、以下のようになっています。今回も左(すごい狭い)がMySQL5.7、右がMariaDB10.1です。
取る際にしくったのかMySQLが狭くなってますが上のグラフがrwlockの待ち時間、下が待ちに入った回数です。とにかくrwlockの待ち時間減少が著しいです。MySQL5.7がsxlockと名前が変わっているのは5.7からS-lock、X-lockに加えてSX-lockが増えた結果、変更されたためのようです。
※この辺は前回のMyNA会のdimstatについてのスライドを見て頂いた方が良いかもしれません。但しMySQL 5.6と5.7の比較です。
その他としては秒間接続数なんかは環境問わずそれだけで速くなる改善かと思います。
MySQL Performance: Improved Connect/sec Rate in MySQL 5.7
MySQL 5.6, 5.7の比較でsysbenchのソースコードをいじってクエリ発行しないようにした比較ですがこちらも以前のMyNA会で計測しているので参考までに載せておきます。
その他ベンチマーク中にぶつぶつTwitterに書いていた内容を@yoku0825さんがまとめてくれてますので参考までに見ていただければと思います。
MySQLベンチマークおじさんがMySQL 5.7とMariaDB 10.1の比較をしていると聞いて
最後に
MariaDBのブログとDimitriさんのブログ、Perconaのブログで5.7との比較したベンチマークが載っていて、Dimitriさんのベンチマークの大半がCPUコア数が増えた際のスケーラビリティについて言及されています(物理72コアでもスケールする)。
そんなブログを掲載したらMariaDBはスライドに載せたコモディティハードウェア(4コア 64GBメモリ!?)でMariaDBの方がreadonlyだと速いと載せてきました。実際MariaDBの方が4コアだと速いようでしたがwhere id = Nのような主キーオンリーで速くても大半のサービスでは嬉しくないわけで。2倍とか3倍差があれば考慮しても良いかなと思いますが10%前後の差です。
※極論、主キー探査しかしないならKVSとか使えば良いわけで(データ量にもよるけど)。RDBの必要無いし。
最近はPCI-E SSD(iodriveとか)を使っている環境ではSlaveサーバはあくまでフェールオーバー用や集計用で、サービスの全てのクエリをMasterで行うケースも結構増えてきてるように感じています。その場合、当然readonlyな状況は滅多に発生しないためreadwriteで速い方を推奨されるかと思います。
Perconaは5.7でMySQL5.7の改善点がほぼ取り込まれると考えられるのでPerconaはスケーラビリティについても追随してくるだろうし、更に改善してくる可能性もあると思います。しかしMariaDBは10.1をMySQL 5.7がGAになる前に出したため、XtraDB5.7(?)を使用すると思われる次のバージョンまではそれなりのreadwriteが発生する環境でMySQL5.7に勝つことは無いと思います。
(GTIDのフォーマットも本家MySQLと違うしどうするんでしょうね?)
最後に主要な設定を載せておきます。
max_connections = 4096 query_cache_type = 0 query_cache_size = 0 performance_schema = ON performance_schema_instrument='%sync%=on' innodb_monitor_enable = 'all' back_log = 1024 sync_binlog = 1 log-bin=mysql-bin master_info_repository = TABLE relay_log_info_repository = TABLE innodb_strict_mode innodb_file_format = Barracuda innodb_buffer_pool_instances = 20 innodb_buffer_pool_size = 40G innodb_log_buffer_size = 64M innodb_log_file_size = 1G innodb_log_files_in_group = 16 innodb_max_dirty_pages_pct = 90 innodb_max_dirty_pages_pct_lwm = 10 innodb_flush_method = O_DIRECT innodb_thread_concurrency = 0 innodb_purge_threads = 4 innodb_read_io_threads = 16 innodb_write_io_threads = 16 innodb_flush_neighbors = 0 / 1 innodb_io_capacity = 5000 / 12000 / 18000 innodb_io_capacity_max = 8000 / 15000 / 23000 innodb_lru_scan_depth = 4000 innodb_open_files = 3000 innodb_print_all_deadlocks = 1 innodb_change_buffer_max_size = 10 innodb_checksums = 1 innodb_checksum_algorithm = crc32 innodb_adaptive_flushing = 1 innodb_adaptive_flushing_lwm = 10 innodb_adaptive_hash_index = 0 / 1 innodb_read_ahead_threshold = 0 / 56 innodb_sync_array_size = 24 / 32 innodb_autoextend_increment = 32 metadata_locks_hash_instances = 48 innodb_max_purge_lag_delay=1000000 innodb_max_purge_lag=100000 innodb_page_size=16k loose-log_timestamps = SYSTEM loose-innodb_buffer_pool_dump_pct = 100 loose-innodb_page_cleaners = 8 loose-innodb_numa_interleave = ON skip-name-resolve