MySQL 5.7が正式にGAとしてリリースされたようです。
というわけでどこが変わったのか、触って見つつ調査してみようと思います。
ちなみにインストール先は AWS の r3.xlarge (Amazon Linux) です。
インストール/セットアップ
Redhat6向けのyumリポジトリをインストールし、mysql-community-serverをインストール。
sudo rpm -ivh http://dev.mysql.com/get/mysql57-community-release-el7-7.noarch.rpm sudo yum install -y mysql-community-server sudo service mysqld start # 原因が把握できていないのですが、mysqlのディレクトリに初期DBが構築されていない事があるようです。 # その場合は、以前のバージョンであれば mysql_install_db を実行して初期DBを構築しますが、 # mysql5.7からは mysqld --initialize に変更されたようです。 mysqld --initialize --datadir=/var/lib/mysql
rootでログインする際の初期パスワードは、下記の様にmysqlのエラーログに出力されるようです。
ノーヒントだったので困った。5.6は .mysql_secret というファイルに保存されていたのに・・
2015-10-22T10:32:43.950929Z 1 [Note] A temporary password is generated for root@localhost: xxxxxxxxxxx
ログインできることを確認したらインストール完了です。
適当にSQLを実行した際、このようなエラーが表示された場合は、 validate_password プラグインが有効になっています。
プラグインを無効化するか、適切なパスワードをrootユーザに設定してください。
(root以外のユーザも、強度の高いパスワードの設定を求められて面倒な為、今回はプラグインを無効化しています。本番環境では有効にしておきましょう)
> alter user root@localhost identified by "xxxxxxxxx"; or > uninstall plugin validate_password;
とりあえずベンチマーク
http://mysqlserverteam.com/whats-new-in-mysql-5-7-generally-available/
5.6から3倍速くなったぜ!と豪語しているので、
別環境に mysql 5.6 をインストールし、sysbench でベンチマークを取ってみました。
sudo yum install -y sysbench --enablerepo=epel echo "CREATE DATABASE sbtest; GRANT ALL PRIVILEGES ON sbtest.* TO sbtest@localhost IDENTIFIED BY 'sbtest';" | mysql -u root -p sysbench --test=oltp --db-driver=mysql --mysql-password=sbtest prepare sysbench --test=oltp --db-driver=mysql --mysql-password=sbtest run
ほどほどにメモリは割り当てています。
innodb_buffer_pool_size = 20G innodb_log_file_size = 512M innodb_flush_method = O_DIRECT max_connections = 100 join_buffer_size = 128M sort_buffer_size = 2M read_rnd_buffer_size = 2M sql_mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES
mysql 5.6の結果
sysbench 0.4.12: multi-threaded system evaluation benchmark Running the test with following options: Number of threads: 1 Doing OLTP test. Running mixed OLTP test Using Special distribution (12 iterations, 1 pct of values are returned in 75 pct cases) Using "BEGIN" for starting transactions Using auto_inc on the id column Maximum number of requests for OLTP test is limited to 10000 Threads started! Done. OLTP test statistics: queries performed: read: 140000 write: 50000 other: 20000 total: 210000 transactions: 10000 (234.00 per sec.) deadlocks: 0 (0.00 per sec.) read/write requests: 190000 (4446.01 per sec.) other operations: 20000 (468.00 per sec.) Test execution summary: total time: 42.7349s total number of events: 10000 total time taken by event execution: 42.6917 per-request statistics: min: 2.67ms avg: 4.27ms max: 17.84ms approx. 95 percentile: 5.02ms Threads fairness: events (avg/stddev): 10000.0000/0.00 execution time (avg/stddev): 42.6917/0.00
mysql 5.7
sysbench 0.4.12: multi-threaded system evaluation benchmark Running the test with following options: Number of threads: 1 Doing OLTP test. Running mixed OLTP test Using Special distribution (12 iterations, 1 pct of values are returned in 75 pct cases) Using "BEGIN" for starting transactions Using auto_inc on the id column Maximum number of requests for OLTP test is limited to 10000 Threads started! Done. OLTP test statistics: queries performed: read: 140000 write: 50000 other: 20000 total: 210000 transactions: 10000 (203.06 per sec.) deadlocks: 0 (0.00 per sec.) read/write requests: 190000 (3858.12 per sec.) other operations: 20000 (406.12 per sec.) Test execution summary: total time: 49.2467s total number of events: 10000 total time taken by event execution: 49.2031 per-request statistics: min: 2.97ms avg: 4.92ms max: 24.68ms approx. 95 percentile: 5.40ms Threads fairness: events (avg/stddev): 10000.0000/0.00 execution time (avg/stddev): 49.2031/0.00
んー、どちらかというと5.7の方がスループットが出ていないような・・
この程度の負荷だと誤差の範囲なのかもしれません。
あとはパラメータチューニングをもっと細かくやるべきなのかも。
JSONテーブルってどんな感じ?
個人的には結構大きいJSONの対応。
PostgreSQLでは既に似たような機能が実装されていたのですが、
RDBMSが複数あるのは微妙ですよね。というわけで採用したことはありませんでした。
そんな中、ついにMySQLに実装されたので、色々と試してみたいと思います。
mysql> create table json_test (id varchar(64) primary key, val json default null); Query OK, 0 rows affected (0.01 sec) mysql> insert into json_test values -> ('key1', '{"id":1, "value":"hogehoge"}'), -> ('key2', '{"id":2, "value":"fugafuga", "option":"optionvalue"}'), -> ('key3', '{"id":3, "value":"foobar", "option":null}'); Query OK, 3 rows affected (0.00 sec) Records: 3 Duplicates: 0 Warnings: 0 [/bash] これでテーブルとテストデータができあがりましたね。 色々とクエリを発行してみます。 一致検索、LIKE検索と、簡単な構文には対応している様子。 mysql> select * from json_test; +------+---------------------------------------------------------+ | id | val | +------+---------------------------------------------------------+ | key1 | {"id": 1, "value": "hogehoge"} | | key2 | {"id": 2, "value": "fugafuga", "option": "optionvalue"} | | key3 | {"id": 3, "value": "foobar"} | +------+---------------------------------------------------------+ 3 rows in set (0.00 sec) mysql> select * from json_test where json_extract(val, '$.id') = 1; +------+--------------------------------+ | id | val | +------+--------------------------------+ | key1 | {"id": 1, "value": "hogehoge"} | +------+--------------------------------+ 1 row in set (0.00 sec) mysql> select * from json_test where json_extract(val, '$.value') like '%hoge%'; +------+--------------------------------+ | id | val | +------+--------------------------------+ | key1 | {"id": 1, "value": "hogehoge"} | +------+--------------------------------+ 1 row in set (0.00 sec) mysql> select * from json_test where json_extract(val, '$.option') is null; +------+--------------------------------+ | id | val | +------+--------------------------------+ | key1 | {"id": 1, "value": "hogehoge"} | +------+--------------------------------+ 1 row in set (0.00 sec) mysql> select json_extract(val, '$.option') from json_test; +-------------------------------+ | json_extract(val, '$.option') | +-------------------------------+ | NULL | | "optionvalue" | | null | +-------------------------------+ 1 row in set (0.00 sec)
という感じで、なかなかそれっぽく動いているようです。
ただ、json内のフィールドとしてはnullとして保存されていても、SQLのnullとは評価されないようですね。。
ドキュメントを読んでもずばりな回答が得られなかったのですが、とりあえずjsonのnullにキャストするとnull値の検索が可能でした。
mysql> select * from json_test where val->"$.option" = cast('null' as json); +------+----------------------------------------------+ | id | val | +------+----------------------------------------------+ | key3 | {"id": 3, "value": "foobar", "option": null} | +------+----------------------------------------------+ 1 row in set (0.00 sec)
そしてjson用の独自構文。
mysql> select * from json_test where val->"$.id" = 2; +------+---------------------------------------------------------+ | id | val | +------+---------------------------------------------------------+ | key2 | {"id": 2, "value": "fugafuga", "option": "optionvalue"} | +------+---------------------------------------------------------+ 1 row in set (0.00 sec)
sqlでアロー演算子は斬新すぎでは?
なんとか楽にフィールドにアクセスできないか、という事で生まれたのでしょうか・・・
まあ助かりますけど・・・
InnoDB周りの改善だったりとか、他にも色々とあるのですが、今日のエントリではこんなところで。