NoSQL と SQL について
かなり古いネタですが、DeNA の松信氏のブログから NoSQL と SQLについて考えてみましょう。
目次
- 目次
- DeNA の松信氏のブログ
- DeNA の松信氏がやった実験
- 一番遅いのはネットワーク
- SQLは滅茶苦茶重いが、速くもできる!
- ユーザアクションに対して SQL は極力1回にする
- まとめ - NoSQL を使うべきとき
DeNA の松信氏のブログ
元記事はこちら。
yoshinorimatsunobu.blogspot.com
日本語訳はこちら。
DeNA の松信氏がやった実験
以下のような SQL を
"select user_name,..
from test.user where user_id=?"
1Gbps の NIC を 4枚挿ししたサーバに対し1千万回投げて、1秒間に処理できた件数を測ったというもの。
結果は以下のようになっています。
意外に思う人が多いとは思いますが、SQL が一番 CPU の利用率が低いです。これは私たち DB屋さんの「CPUを使い切る方が難しいよね」という感覚が実験結果でも再現されていると言えます。CPUを使い切るとしたら、よっぽど下手くそな SQL を書くか、GIS など内部的な計算が異常に多くなる処理をしなければ 100%に張り付くなんてことは起きないのです。
一番遅いのはネットワーク
全てのデータがメモリ上にキャッシュされている(松信氏の実験)ことを前提とすると、一番遅いのはネットワークで、この実験の場合、理論値でも1Gbpsしか出ていません。
他の条件として、memcached も、SQLを使わないでデータにアクセスしていますが、Handler Socket は、MySQL の API を利用して SQL を使わないでデータにアクセスしています。つまり、データにアクセスする部分については、SQLを使ったときと同じなのです。
そこから、結果をイメージ化すると図のようになります。
松信氏のブログから、リクエスト、レスポンスもネットワークの負荷が小さくなるように工夫したと書いてあるので、そのようにして、4倍差、7倍差をつけてみました。
memcashed のデータ処理の速度が MySQL と同じではないでしょうが、大差はないと仮定して作っています。いずれにしても、SQLのオーバーヘッドと、ネットワークの処理時間が大きくなければ、4倍(memcashed)7倍(Handler Socket)という速度差は成り立ちません。
SQLは滅茶苦茶重いが、速くもできる!
RDB(SQL の概念)が発表されたのは1969年。50年前です。
ネットワークは今とは桁違いに遅い
端末に処理能力がない
という条件のもとに考え出された概念ですから、サーバで一括処理して端末に結果だけを送る。という前提で作られています。
つまり、
"select user_name,..
from test.user where user_id=?"
というような SQL を「1千万回も送る」というような処理は、そもそも想定されていないのです。
それぞれを限界までチューニングするという風にして条件をそろえるなら、
"select user_name,..
from test.user where user_id between 1 AND 2500000"
という SQL × 4(ポートの数)と、memcached や、Handler Socket を比べることになるでしょう。そうすれば100% SQLの方が速いと断言できます。
処理にもよりますが、数回~数十回の NoSQL の処理を、1回の SQL にまとめることができた時点で逆転します。
ユーザアクションに対して SQL は極力1回にする
つまり、ユーザアクションに対して SQL の発行は極力1回に抑えるべきです。
ですから、「1回のユーザアクションに対して、1件のレコードしか処理しない」という要件のときには、RDBMS を使うべきではありません。
「1回のユーザアクションに対して、1件のレコードしか処理しない」というようなことが比較的多いシステム(例えばゲーム)のときは、Handler Socket や、NoSQL API のようなものを使い、複数のレコードを処理できるときは SQL を使うという併用が良いでしょう。
まとめ - NoSQL を使うべきとき
SQL(RDBMS)は、もちろん完璧ではありませんから、何でもかんでも使えばよいということではありません。NoSQLを選択すべきときは以下のようなシステムのときになります。
- 極端に否定形のデータを扱う(ドキュメント型)
- レコード単位の処理がない(列指向)
- レコード単位の処理しかない(KVS)
レコード単位の処理も、複数のレコード単位の処理もある。というときは、Handler Socket や、NoSQL API のような SQL の解析をスキップできるものと、SQLの併用。
レコード単位の処理が少ないときは、SQL になるでしょう。