外部キー制約、来たる!
何を差し置いてもまず重要なのが、外部キー制約である。長年InnoDBでは使えるが、MySQL Cluster(NDBストレージエンジン)には実装されていなかった。外部キー制約が使えないという理由でMySQL Clusterを採用しなかったという人も多いだろう。だが、それはこれまでの話だ。MySQL Cluster 7.3なら外部キー制約が使える!!
メジャーどころのRDBMSなら当たり前のように搭載されている外部キー制約であるが、これがあるのとないのとでは、データベース設計の自由度が段違いである。
使い方はInnoDBの場合と同じなので、詳しいことはマニュアルでも読んで頂きたい。
MySQL 5.6 Reference Manual :: 13.1.17.2 Using FOREIGN KEY Constraints
劇的な性能の改善
これまでのバージョンには、実はNDB APIの内部に有名なボトルネック、すなわちジャイアントロックが存在した。そのロックはTransporter Mutexと呼ばれるもので、データノードとの通信を保護するものだが、このロックに頼りすぎているためスケールしなかった。MySQL Cluster 7.3ではこのジャイアントロックをより粒度の細かい複数のロックに分割ないしは置き換えることでボトルネックが解消され、SQLノードの性能が劇的に改善した。次のグラフはMySQL ClusterのプロダクトマネージャーであるAndrew Morgan氏のブログから拝借したものである。出展:MySQL Cluster 7.3 is now Generally Available – an overview @ Andrew Morgan’s MySQL Cluster Database Blog
見よ!この劇的な変化を!
これまでのバージョンでは全体的な性能を向上させるために、SQLノードをたくさん並べる必要があった。だがMySQL Cluster 7.3なら性能を出すために必要なSQLノード数はずっと少なくなるだろう。そして複数のCPUコアをより効果的に使うことができるだろう。同じ性能を出せるならノード数は少ないほうがいい。既にMySQL Clusterを使っていて、SQLノードが一つか二つぐらいしかないよ!という場合には、MySQL Cluster 7.3にアップグレードするだけで劇的に性能が向上することだろう。
なお、この性能改善はSQLノードだけの話ではない。NDB APIを使ったすべてのアプリケーションが影響を受けるため、NDB APIのネイティブアプリやndb-memcachedなどの性能も改善することになる。
JOINの性能が改善
MySQL Clusterと言えば「JOINが遅い」というのが代名詞であった。「なんのっ!サブクエリはもっと遅いよ!」なんていう自虐ネタはおいといて、MySQL Cluster 7.3ではJOINの性能がさらに改善している。何故か?
それはSQLノードがMySQL 5.6ベースになったからだ!MySQL 5.6にはBatched Key Access Joinというアルゴリズムが追加されている。これがどのようなアルゴリズムかについては、過去に以下の記事で解説したのでそちらを参照して頂きたい。
Block Nested Loop Join/Batched Key Access Join(1/3):企業のIT・経営・ビジネスをつなぐ情報サイト EnterpriseZine (EZ)
実はJOINの性能であれば一つ前のバージョンであるMySQL Cluster 7.2でも大幅に改善した。Pushdown Join(AQLやSPJという別名がある)というアルゴリズムが追加され、データノードで並列にJOINを処理できるようになったからだ。これは他のストレージエンジンにないユニークな機能であり、Pushdown JoinのおかげでJoinの性能が70倍にも改善されたケースすらレポートされている。ハマればもっと改善することもあるだろう。
ならばPushdown Joinでオッケーじゃん?なんでBKA Joinが必要なの?と思われるかも知れない。
BKAが必要な理由は簡単で、Pushdown Joinには制限があるからだ。以下は「漢(オトコ)のコンピュータ道: MySQL Cluster 7.2見参!Webでも使える熱いヤツがやってきた。」からの抜粋だが、Pushdown Joinだけでは対応しきれないケースが多々あることがわかる。
- JOINするカラムの型はまったく同じでなければならない。(BIGINTとINTはSPJできない。)
- クエリの結果にBLOBまたはTEXTが含まれてはいけない。
- FOR UPDATEは非サポート
- サポートしているJOINのレコードアクセスタイプはeq_refまたはconstのみ。
- ユーザーレベルパーティショニング(別名Distribution Awareness)が行われたテーブルは非サポート
Pushdown Joinが使えないケースはBKAが補完できる。MySQL Clusterのメインの開発者であるJonasが以前発表したスライドでBKAとPushdown Joinについての解説があるのでぜひこちらも見て頂きたい。
ちなみに、MySQL 5.6では他にも様々な改善が行われている。IN/EXISTSサブクエリのSemi-Join最適化などの恩恵も授かることができるので、MySQL Clusterでもサブクエリのパフォーマンスが改善されることになる。もちろんSemi-JoinもPushdown JoinやBKAで実行できるので、サブクエリの実行速度も劇的に改善されることになる。もう自虐ネタは卒業だ!
Node.js
前回のバージョンであるMySQL Cluster 7.2でmemcachedインターフェイスが追加されたのに続き、今度はNode.js用ドライバが追加された。MySQL Clusterは高速なNDB APIによるアクセスがウリだが、そのままでは若干使い勝手が悪い。そこで、使いやすいNoSQLインターフェイスを着々と拡充しているというワケだ。ネイティブのNDB API(C++)よりは劣るが、実用的な速度でアクセスが可能となっている。NDB APIのボトルネックが解消した影響は、NoSQLインターフェイスにも好影響を及ぼすだろう。とりあえず使い方についてはマニュアルを参照のこと。
MySQL Cluster API Developer Guide :: 5 MySQL NoSQL Connector for JavaScript
Auto Installer
MySQL Clusterはインストールと設定がなかなかに面倒くさいソフトウェアである。複数のホストにソフトをインストールしなければならないし、必要なディレクトリを作ったりサイジングをしたりと何かと手間がかかる。それを少しでも軽減するために導入されたのがAuto Installerだ。ウィザード形式のGUIで、一挙に複数のホストをまとめて設定できる。詳しくはマニュアルを参照していただきたい。MySQL 5.6 Reference Manual :: 17.3.6 The MySQL Cluster Configuration Wizard
チュートリアル動画もあるよ!
まとめ
これまでのバージョンのMySQL Clusterは、やはりある程度特殊な用途で使うという感じが否めない面があった。だが、MySQL Cluster 7.3はようやく普通のRDBMSとして使えるデータベースソフトウェアに仕上がってるように思う。外部キー制約の導入とSQLノード側の性能改善のインパクトは大きく、隙がなくなったと言えるかも知れない。(今まで隙だらけだったとも言えるが。)これまでMySQL Clusterを敬遠していた人も是非一度試して欲しいと思う。とはいえ、MySQL Cluster 7.3は万人にオススメできるRDBMSではない。複数のホストが連携するため運用も複雑になるし、何よりホスト数が増えればその分コストが高くつくからだ。いくら使いやすくなったとはいえ、RDBMSが必要ならやはりまずは通常のMySQLを検討するべきだろう。しかし要件次第ではMySQL Clusterが好ましいというケースは結構ある。例えば次のようなニーズがある場合にはMySQL Clusterを検討する価値があるだろう。
- Active/Activeの高可用性構成が欲しい。
- 高い更新性能が欲しい。
- スケールアウトしたい。
- 大規模なデータをインメモリで扱いたい。
- NoSQLによる高速なアクセスしつつSQLでも同じデータにアクセスしたい。
- スキャンやJOINをデータノードで並列処理したい。
- 通常のMySQLで開発した資産を活かしたい。
というわけで、ぜひMySQL Cluster 7.3をダウンロードして頂きたい。
奥野さま、
返信削除構築・運用バイブルでいつも助けられています。
いままで何とかしのいできたのですが
mysqld: Sort aborted: Lock wait timeout exceeded; try restarting transaction
が定期的に20分毎に発生する症状に悩まされています。
mysql-5.5.29 ndb-7.2.10を使っていて、データノード4台、SQLノード8台ほどで、いつもトータルで10000qps、アップデートで1000qps程度で動いていますが、この辺りを超えると
全部のSQLノードで上のメッセージが出てSQLノードがオフライン・オンライン状態になってサービスが再度開始される状態になります。
20分ほどというキーワードがカギのようなのですがどうも原因がわからずに困っています。
なにかチェックしたらいい点等はありますでしょうか。
TransactionDeadlockDetectionTimeout=2400
と増やしてみましたがまったく変わりませんでしたし、データノードは最大でもCPU利用率が5%程度でアイドル状態です。ただ、仮想サーバでの稼働ということでndbdを使っています。
Hashimura Masayuki さん、コメントありがとうございます。
返信削除Lock waitはDBTCが制限時間内に対象の行に対するロックを獲得できなかった場合に発生するエラーです。行レベルロックに対するデッドロックがおこったり(NDBにはInnoDBのようなデッドロック検知機能はありません)、長時間かかるクエリがロックを解放しなかったり、DBTCとは異なるノードにあるレコードをロックする必要がある場合にネットワークがとても遅くなっていたりといった原因が考えられます。
要因は様々ですので、概要を聞いただけではなんとも判断し難いところがあります。上記のような要因がありますので、目星をつけてあたってみてください。まずはスロークエリログあたりからでしょうか。
コメントありがとうございます。
返信削除いろいろバッファ関連を増やしたりしてみましたが全く変わらない様なのでquery logを取得してみんなで確認してみたいと思います。
Google Books版の「MySQL Cluster構築・運用」を個人でも購入させていただきました。
奥野様もご健勝で頑張ってください。
書籍の購入ありがとうございます。
返信削除取得するべきなのは「スロー」クエリログです。まずはロックを掴みっぱなしにしてるUPDATE等がないかどうかを調べるのが王道ですね。あと、この記事にあるように、7.3にアップグレードするとクエリの効率が向上するのでオススメです :)
PDF版の書籍をGETしました。
返信削除http://gihyo.jp/book/2012/978-4-7741-5053-6
SQLノードへDBクライアントからの構成例があるとイメージしやすいなぁと思いました。今のところ、SQLノードとDATAノードとDBクライアントを物理1サーバに1セットにしようと思っています。迷っているのは、DBクライアントからSQLノードへのアクセスをlocal接続(UNIXソケット)にすべきか、上記のLBの仮想IPにて分散させるかです。この図が大変イメージしやすかったです。
http://nippondanji.blogspot.jp/2009/02/mysql-cluster.html
Ishizaka Takehiko さん
返信削除コメントおよび電子書籍の購入ありがとうございます。
書籍のほうではp.32からの解説がこのこのブログ記事の内容に該当するのですが、少し書き足りない感じがしますね。改訂があれば加筆したいと思います。