ちょっと硬派なコンピュータフリークのBlogです。

カスタム検索

2012-10-01

開発スピードアクセル全開ぶっちぎり!日本よ、これがMySQL 5.6だッ!!

米国で行われているMySQL Connectというイベントで、ついにMySQL 5.6 RC(リリース候補版)が発表された。リリース候補版ということは、これが次の正式版になるということだ。MySQL 5.5は5.1から凄まじい進化を遂げたバージョンであった。だが、MySQL 5.6はさらにそれを上回る進化を遂げている!正直ここまでの進化を誰が予想しただろうか、いや誰も出来なかったであろう。これまで、α版が出たときから何度か新機能について紹介してきたが、今回改めてMySQL 5.6の新機能を振り返ってみようと思う。すべてまとめるともの凄い内容だ。興奮して夜も眠れなくなること請け合いだ。MySQLの進化が止まるのでは?などという心配は吹き飛び、もはやもうちょっと小出しにしなくて良かったのか?と心配してしまうレベルである。

それではMySQL 5.6の新機能について紹介していこう。

InnoDB


MySQL 5.5ではスケーラビリティの向上を始め大幅な改善が見られた。MySQL 5.6ではまたもやInnoDBは大幅な改良が加えられている。

インデックスの追加と削除がオンラインで可能に

思わず「おおっ!!」と声が上がりそうな内容であるが、セカンダリインデックスの追加や削除がオンラインで(つまり他の操作をブロックすることなく)実施可能になった。InnoDB PluginではFast Index Creationという機能が追加され、スキーマ変更においてテーブル全体をコピーするのではなく、セカンダリインデックスの追加時にそのインデックス部分だけを再構築するようになった。だが、その操作はオンラインではなく、DDL実行中はそのテーブルへの参照だけが出来る状態になっていた。

だが!MySQL 5.6ではALTER TABLE...ADD INDEX/DROP INDEX中であっても参照・更新共に実行可能になったのである。

FULLTEXTインデックスのサポート

InnoDBでFULLTEXTインデックスがサポートされるようになった。これまではMyISAMでのみサポートされていたが、ついにInnoDBでも利用可能になったのである。

.ibdファイルのエクスポート・インポート

innodb_file_per_tableオプションを使用したとき、ひとつの.ibdファイルを他のMySQLサーバーへ持って行ったら動かないというのは、非常に多くの人が経験する間違いであった。.ibdファイルを他のマシンへ移動できればいいなー。そう夢見たひとは決して少なくないはずである。そして今、その夢が現実のものとなった!!

FLUSH TABLES table_name FOR EXPORT

でテーブルの移行を準備し、.ibdファイルと、コマンド実行時に生成される.cfgファイルを移行先のマシンへコピーする。そして

ALTER TABLE table_name IMPORT TABLESPACE

で取り込むことが出来るという寸法だ。

ページサイズの指定

これまでInnoDBのページサイズは16KB固定で、それを変更するには再コンパイルが必要であった。だが、4KBと8KBのページサイズについてはオプションで指定が可能になった。ただしテーブル単位でページサイズを指定するということは出来無いので、SSD使用時など(Random Readが得意なストレージを使用しているときなど)にはページサイズを変更してみると性能が向上するかも知れない。

バッファプールのディスク書き込み処理の改善

InnoDBのバッファプールの内容をディスクへ書き込む処理(いわゆるflushing)がかなりきめ細かく調整できるようになった。その結果、更新の負荷が高いシステムではかなり恩恵に預かることが出来るだろう。

memcached

InnoDBテーブルに対してmemcachedインターフェイスを通じてアクセスできるようになった。既にhandlersocketを使ってる人は多いだろうが、MySQL 5.6ではmemcachedプロトコルという選択肢が増えることになる。参照の負荷が凄まじい場合に強い味方になってくれるはずだ。

インデックス統計情報の改善

InnoDBのインデックス統計情報は必要に応じて自動的に収集されるようになっていたが、抽出するサンプル数が固定であったり、再起動時に統計情報がクリアされてしまうといった問題があった。(そのためたまに好ましくない実行計画が選択される場合があった。)しかし、MySQL 5.6ではインデックス統計情報にもテコ入れが入り、統計情報をディスクへ保存できるようになったり(再起動時に消えない)、手動(ANALYZE TABLEコマンド)だけで統計情報を更新することができるようになったり、サンプル数を調整したりできるようになった。

START TRANSACTION READ ONLY

START TRANSACTION READ ONLYというシンタックスがサポートされるようになった。これにより、Read-onlyな処理が高速化される。内部的な要因により、更新のための準備をしないことでオーバーヘッドの削減となるためだ。もし参照がメインの場合には使用して見ていただきたい。

ログサイズの上限変更

これまでInnoDBのログサイズの上限は合計で4GBまでであった。しかし昨今の巨大なメモリを搭載したマシンではこれはしばしば不十分である。MySQL 5.6ではログファイルの上限が512GBに拡張されている。

デッドロック検出機能の改善

InnoDBにはデッドロックの検出機能が搭載されているが、MySQL 5.6では従来より高速な検出アルゴリズムが使用されるようになった。(そのため更新処理の性能が向上することになる。)そして何気に嬉しいのが、デッドロックが検出された場合に、情報がエラーログへ出力されるようになったことだ。デッドロックの解析がずっと楽になるだろう。

CPUスケーラビリティの向上

ロックの改善によりCPUスケーラビリティが向上している。並列で多数のトランザクションを実行する場合に性能が向上することになる。

再起動時にバッファプールの内容を復元

InnoDBシャットダウン時に、バッファプールにどのような内容が格納されていたかという情報(バッファプールのデータそのものではない)をディスクへ保存できるようになった。再起動時にそれの内容を復元することにより、暖機運転をする必要がなくなった。

レプリケーション


すでにInnoDBの改善だけでもお腹いっぱい!!ではないだろうか。筆者はすでに記事を書く手が疲れてきているほどだッ!!だが、MySQL 5.6の進化はまだまだ紹介し足りない。次はもうひとつの目玉、レプリケーションだ。

フェイルオーバー

MySQLユーザーの長年の夢。それはレプリケーションのフェイルオーバーである。すでに松信氏によるMHAによって成し遂げられてはいるが、MySQL 5.6では異なる方式によってフェイルオーバーが出来るようになった。Global Transaction IDというIDがバイナリログの各イベントに付与されることで、それがスレーブ側のバイナリログに書きこまれた場合でもイベントを一意に特定できるようになった。そのため、

  • どのスレーブが一番進んでいるか?
  • どこからレプリケーションを再開するべきか?

ということが瞬時に判別可能なのである。MySQL Utilitiesを使うことで、自動的なフェイルオーバーが可能である。(参照:Replication and auto-failover made easy with MySQL Utilities @ Andrew Morgan’s MySQL Cluster Database Blog

クラッシュセーフなスレーブ

レプリケーションを運用する上で、何気に悩みの種となっていたのがスレーブのクラッシュではないだろうか。MySQL 5.5までのスレーブはクラッシュセーフではない。それはつまり、スレーブがクラッシュしたらマスターとの同期がくずれ、スレーブを再セットアップする必要が生じるということだ。特にスレーブがたくさんある場合にはクラッシュする確率も上がってしまい、再セットアップをする機会も増えてしまう。

MySQL 5.6ではレプリケーションの情報をテーブルに格納することができるようになった。InnoDBを用いることにより、レプリケーションの情報がテーブルの中身と確実に同期するようになったのである。

チェックサム

バイナリログにチェックサムが付与されるようになった。そのため、バイナリログが転送の途中で壊れてしまった場合に検出することができるようになった。スレーブがバイナリログの損傷を検出した場合には、バイナリログの再送がおこなわれる。

遅延レプリケーション

遅延レプリケーションとは、スレーブ側でバイナリログの適用をあえて遅らせるという機能である。そのようなスレーブをもうけておくことにより、マスターでオペミスをやらかしてしまったなど、いざという時に代替機として利用することができる。

mysqlbinlogコマンドによるバイナリログのバックアップ

従来バイナリログをバックアップするときはファイルコピーによるバックアップだが、mysqlbinlogコマンドでもおこなえるようになった。

スレーブが使用するNICの指定

スレーブに複数のNICがついている場合、レプリケーションをどのNICを通じて行うかを指定できるようになった。ネットワークのトラフィックが多い場合に重宝することになるだろう。

マルチスレッドなスレーブ

スレーブSQLスレッドがデータベース単位で並列実行可能になった。データベース単位なので使いどころは難しい部分があるだろうが、スレーブの遅延に対するひとつの解決策となるだろう。

オプティマイザ


もう勘弁してくれ?これ以上進化してどうするってんだ??という声が聞こえてきそうだが、肝心な内容をまだ伝えていない。そう、オプティマイザの改善だ!!

個人的にはこれが今回のバージョンで一番のポイントだと思っている。実行計画が効率的になれば無駄な仕事が大幅に減るからだ。

Semi-Join最適化

もう「サブクエリが遅い」なんて言わせない!!

MySQL 5.6ではサブクエリが内部的にSemi-JoinというJOINの一種として実行することが可能になった。従来は「相関サブクエリは遅いから・・・」と手でJOINに書き換えるということが多かったが、MySQL 5.6ではそのようなケースはほとんどなくなるだろう。(ちなみに、Semi-Joinとは重複のないJOINのことである。)

MySQL 5.6ではJOINのアルゴリズムにも改良が加えられているが、それらは当然Semi-Joinにも適用される。

もう一度いう。

もう「サブクエリが遅い」なんて言わせない!!

FROM句のサブクエリの改善

これまでのバージョンでは、FROM句のサブクエリは必ずマテリアライズされていた。(つまり、外部クエリより先に実行され、その結果がテンポラリテーブルに格納されていた。)FROM句のサブクエリは、レコードが実際に必要となるまで実行を遅らせるようになった。その結果、FROM句のサブクエリが含まれるEXPLAINや、LIMIT句がついた場合などに効率化が期待できる。

(知らない人が)FROM句のサブクエリに時間がかかって驚くというのはMySQLにおいてよく見かける光景である。

また、マテリアライズされた場合に、そのテーブルからのフェッチを効率化するためのインデックスが追加されるようになっている。

EXPLAINの改善

これまでのバージョンではEXPLAINはSELECTしかサポートしていなかった。しかし、MySQL 5.6ではUPDATE/DELETE/INSERTなども直接EXPLAINで実行計画を調べることが出来るようになった。何気に嬉しい改善である。

各種アルゴリズムの改良

MySQL 5.6では、テーブルからレコードをフェッチする際のアルゴリズムが大幅に強化されている。Batched Key Access Join、Multi Range Read、Index Condition Pushdownなどだ。これらのアルゴリズムの詳細については、以前EnterpriseZineに投稿したので、そちらを参照して欲しい。クエリがこれらの実行計画にピタリとハマればかなりの性能改善が見られるだろう。ハマらなければ関係ないのだが。

ORDER BY ... LIMITのパフォーマンス改善

SELECT ... FROM single_table ... ORDER BY non_index_column [DESC] LIMIT [M,]N;

という構文を持つクエリは、ウェブアプリケーションにおいて非常によく見かけるもののひとつである。MySQL 5.6ではこのタイプのクエリが高速化されている。インデックスがないカラムでソートする場合にはファイルソートが行われるが、従来のバージョンではすべてのレコードをソートバッファおよびテンポラリファイル内に保持しており、最後に結果を統合して上位のN行だけをクライアントへ送信するというアルゴリズムであった。MySQL 5.6では、上位のN行が必ずソートバッファに収まるということがわかっている場合には、ソートバッファ内で上位のレコードだけを保持するように改良されている。その結果、ファイルアクセスを行わないことにより格段に処理が効率化する。

オプティマイザトレーシング機能

これまでオプティマイザの挙動を知る唯一の手がかりはEXPLAINであった。MySQL 5.6ではさらに詳細な挙動を知るためのオプティマイザトレーシングという機能が追加されている。オプティマイザがどのような情報を元にその実行計画を選んだかということが、より明確に判断できるだろう。とりあえずマニュアルに載っている例を見て欲しい。どのような情報が得られるかが一目瞭然である。

パーティショニング


MySQL 5.1で追加されたパーティショニングであるが、これもまたバージョンを追うごとに着実に進化を続けている。今回のバージョンでもより使いやすく、より高速になっていく様子が伺える。

パーティション数の上限が1024から8192に増加

読んで字のごとく。ひとつのテーブルに設定可能なパーティション数が向上している。特にサブパーティションを使用する場合には1024で足りない場合が多かったと思うが、使用可能なパーティション数が8倍になったことでかなりパーティションを利用するシーンが増えるのではないだろうか。

パーティションをテーブル間で移動

同じ構造を持つテーブル間でパーティションの移動が可能になった。古くなったレコードをアーカイブ用のテーブルに移すといった場合に便利である。構文は以下の通り。

ALTER TABLE pt EXCHANGE PARTITION p WITH TABLE t

詳細はマニュアルを参照して欲しい。

明示的なパーティションの指定

クエリ実行時に明示的にパーティションを指定できるようになった。構文は次の通り。

SELECT * FROM t PARTITION (p0, p1) WHERE c < 5
このように指定することで、テーブル全体からレコードをフェッチするのではなく、特定のパーティションだけを対象にすることができる。従来はWHERE句の条件から使用するパーティションが算出された。そのため、意図しないパーティションが検索の対象になってしまうということがしばしば発生した。だが、MySQL 5.6では確実に対象のパーティションを指定することができる。
テーブルロックの改善
MyISAMのようなテーブルロックを使用するストレージエンジンが対象となるが、パーティショニングを使用した際にロックの範囲がそのパーティションだけに限定されるようになった。そのため、例えば更新が特定のパーティションに限ったものであれば、同時に他のパーティションのレコードを参照・更新することが出来る。 パーティショニングを活用すれば、MyISAMの同時実行性能が多少改善することになるだろう。

セキュリティ関係

.mylogin.cnf
従来、$HOME/.my.cnfにログイン用のユーザー名とパスワードを記述することにより、ログイン時の入力を省略することができた。しかしながら、.my.cnf内のパスワードは平文なのでセキュリティ上の懸念があった。MySQL 5.6では、.mylogin.cnfに暗号化されたパスワードを格納することで安全性を高めることができるようになった。.mylogin.cnfの内容を編集するには、mysql_config_editorというコマンドを使用する。
SHA256パスワードプラグイン
従来はMySQLのPASSWORD関数によって生成されたハッシュによってパスワードの認証が行われていた。MySQL 5.6ではパスワード認証においてSHA256によるハッシュを利用することが可能になった。詳細はマニュアルを参照して欲しい。
パスワードの期限
パスワードをexpireさせることができるようになった。
パスワードの強度の指定
パスワードバリデーションプラグインを使用することで、パスワードの強度を指定することができるようになった。パスワードの強度がポリシーに達していない場合には、次のようなエラー(ER_NOT_VALID_PASSWORD)が返される。
mysql> SET PASSWORD = PASSWORD('abc');
ERROR 1819 (HY000): Your password does not satisfy the current policy
requirements
mysql_upgradeによる古いパスワードのチェック
古いタイプの(4.0以前の)パスワードを使用していると、mysql_upgradeが警告を発するようになった。
ログの安全性向上
ログファイル内にパスワードが平文で記述されないようにすることが出来るようになった。従来通りそのままログにパスワードを含めたい場合には、--log-rawオプションを使用する。
スレーブのパスワード
従来はmaster.infoにユーザー名とパスワードが記載されていたが、START SLAVE実行時に指定することができるようになった。

その他

LOCK_open
長年、MySQLにおいてボトルネックとしての定位置を築きあげてきたジャイアントロックであるLOCK_openが、ついにその座を奪われることになった。詳細はMikael Ronstrom氏のLOCK_open finally removed as a bottleneck in MySQL 5.6 というエントリを参照していただきたいが、"We have seen at least 70% improvement based on just adding this new feature and in some cases the gain can probably be even bigger."ということらしい。同時実行数が多い場合にはかなり期待ができるだろう。 ちなみに、LOCK_open自体がなくなったわけではなく、このロックで守られていた処理がより細かなロックに分割されたというものであるので、誤解のないように注意されたい。
ホストキャッシュ
PERFORMANCE_SCHEMAに追加されたhost_cacheというテーブルで、ホストキャッシュを参照することができるようになった。どのクライアントがエラーを発していたかということを知るには、ホストキャッシュの内容を知ることが不可欠であるが、これも長年実装されてこなかった。PERFORMANCE_SCHEMAという土台が整い、ついにMySQL 5.6で陽の目を見ることになったのである。
Performance Schema
host_cacheテーブル以外にも、パフォーマンススキーマには大幅な改良が加えられている。特に、テーブルごとの統計情報が取れるようになったのが大きい。どのテーブルから何行フェッチしたか、更新したか、挿入したか、削除したかが分かるようになった。それだけでなく、どのテーブル操作時にどれだけのI/O待ちやロック待ちが発生したかが分かるようになったので、チューニングすべきテーブルが特定しやすくなったのである。
OpenGIS
従来、ジオメトリを計算する関数では、MBR(Minimum bounding rectangle)を用いたアルゴリズムしか提供されなかったが、MySQL 5.6ではオブジェクトの形状に沿った判定が可能になった。
小数点以下の秒
TIME、DATETIME、TIMESTAMPにおいて小数点以下の秒(ミリ秒やマイクロ秒)を指定することができるようになった。小数点以下の桁数はカッコで指定する。
CREATE TABLE t1 (t TIME(3), dt DATETIME(6));
ストアドルーチンの改善
Diagnostic Areaが追加され、ルーチン内で発生したエラーの処理をより柔軟におこなうことができるようになった。

まとめ

というわけで、MySQL 5.6はとんでもなく進化したバージョンになった。現在はまだリリース候補版なので、正式版になるのを楽しみにしていて欲しい。 MySQL 5.6では、長年MySQLユーザーが欲しいと思っていた機能が多数追加され、かなり隙がなくなったように思う。高度な機能を追及すればキリはないが、現在MySQLが活躍している現場では、MySQLに対する不満はほぼ解消されるのではないだろうか。一部では「MySQLの開発が止まるのではないか?」という不安な声が囁かれているが、事実はまったく異なる。MySQL 5.6は未だかつて無いほどの大幅な機能アップを果たしているのである。 MySQL 5.6.7RCは、現在MySQLのダウンロードサイトから入手可能である。(Development Releasesタブを選択すること。)ぜひ色々と試してみていただきたいと思う。 なお、本エントリではそれぞれの機能についてあまり深くは解説していない。詳細を知りたい人はぜひ過去のエントリも参照していただきたい。 また、db tech showcase 2012というイベントにて、このへんの話を詳しく解説する予定である。

0 コメント:

コメントを投稿