NoSQLとSQLについて
NoSQL(Not Only SQL)とは、SQLを使わないKVS(Key Value Store)などを指しますが、最近流行のキーワードです。今日はNoSQLについて。
SQLは英語であり仕様書である
SQLは英語であり仕様書である。と書いてきました。
SQLは、プログラム(アルゴリズム)を組むことができない文系の事務員が、英語的記述で書けば結果が得られるというものです。SQL文中にアルゴリズムは存在しません。
例えば、次のようなテーブルをご用意ください。
TEST_TABLE
ID NUMBER 主キー
NAME VARCHAR(20)
IDに1から1,000,000
NAME 名前のテストデータ
この100万件のデータが入ったこのテーブルを
1) SELECT * FROM TEST_TABLE WHERE ID = 1
2) SELECT * FROM TEST_TABLE WHERE ID BETWEEN 1 AND 200
3) SELECT * FROM TEST_TABLE WHERE ID BETWEEN 1 AND 300000
の3つのSQLの実行計画を採ると以下のようになります。
1)はインデックススキャン
2)はインデックスの範囲スキャン
3)はTEST_TABLEの全走査して読み飛ばし
SQL文には、一切、アルゴリズムを示す文言はありませんが、オプティマイザが自動的にインデックスを使うべきか、使わないべきか判断して実行するわけです。
また、結合(JOIN)処理では、ベンダーによって違いますが、主に3種類の結合を自動的に使い分けます。
【SQL文】
テーブルA
INNER JOIN テーブルB
ON テーブルA.B_ID = テーブルB.ID
【結合(JOIN)処理】
・ネスティッドループ
テーブルAを一件ずつループ処理していく。
テーブルB.ID を テーブルA.B_ID の値で検索。
データが存在すれば、テーブルA、テーブルBのデータを出力する。
・ソートマージジョイン
テーブルA を B_ID でソートする。
テーブルB を ID でソートする。
両方のテーブルをループしながら、IDが一致するときデータを出力する。
・ハッシュジョイン
テーブルA の B_ID をハッシュ関数を用いてハッシュテーブルを作成
テーブルB.ID のハッシュキーと先ほどのハッシュテーブルと一致するとき
ハッシュテーブルのポインタからテーブルAのデータを特定し、
テーブルA.B_ID = テーブルB.ID と一致するか確認。
一致するときデータを出力する。
これもSQL文にはアルゴリズムが全く含まれていないにもかかわらず、インデックスの有無やデータの分散具合で、オプティマイザが自動的に使い分けます。
SQL文にコメントとして「ヒント」を記述することも可能ですが、あくまでもコメントで「ヒント」です。オプティマイザが「ヒント」の通り実行計画を作るとは限りません。
全くもって、仕様書を書くSEとプログラミングするPGの関係に似ていると言えるでしょう。
NoSQLはタイヤの再開発
NoSQLはタイヤの再開発をすることになります。
これまで書いて来たようにSQLは非常に単純な記述で(アルゴリズムなしに)結果を得ることができます。一方、自動でアルゴリズムまで作ってくれる分、どうしてもオーバーヘッドが大きくなり、単純な処理ほどオーバーヘッドの影響が大きくなります。また、RDBMSの一貫性の維持のために掛かるコストも大きく、スケールアウトも難しいです。
NoSQLは、SQLがトレードオフしてきた
単純な処理が遅い
スケールアウトが難しい
という問題に対するアンチテーゼです。
逆に、NoSQLを採用すれば、今度はRDBMSが自動で行ってきた処理を、別途、構築する必要が出てきます。
NoSQLを採用するならば、オプティマイザが行っている機能も、RDBMSのメリットも、デメリットもよく理解する必要があるでしょう。その上で、「タイヤの再開発」することになったとしても、「単純な処理が速い」「スケールアウトし易い」というNoSQLのメリットの方が大きい。となるならばNoSQLを採用するべきです。
当たり前の話で、「これからはNoSQL」とか「新しいxxx」などというキャッチフレーズをそのまま採用基準にするようでは技術者とは言えません。技術的に費用対効果を計算すべきでしょう。
NoSQLは騒ぎすぎ
SQL、NoSQLのメリット、デメリットを踏まえて、具体的に NoSQL を採用するとすると、
1)システム自体は単純であること
2)一貫性の問題がないこと(決済情報などを含まないこと)
3)最大トラフィックが非常に大きく、予想が困難なこと
という条件が揃う必要があります。
これらの条件が揃うシステムというのは
1)コンシューマ相手のサービスであること
2)決済情報を含まないこと
3)ユーザ数が固まってないこと
というようなシステムになります。
例えば Twitter が上げられます。Twitterのユーザが100人だったとしたらRDBMSで作ればすぐにリリースできます。システムが単純なだけにNoSQLでも工数の差はそれほど大きくないでしょうが、SQLの方が早くできます。しかし、現在のように数千万、数億のユーザであればRDBMSでは全く効率的ではありません。
一方、コンビニエンスストアーは、大変巨大なデータベースを備えていますが、システムは非常に複雑で、一貫性の維持機能をNoSQLで作るコストより、RDBMSで作るコストの方が安くつくためNoSQLは採用されません。
日本には上場企業が約4000社あります。そのほぼすべてにRDBMSを利用したシステムが導入され稼働していると考えて間違いありません。その中で、コンシューマ向けのサービスを行っている企業は、「情報・通信」、「小売業」、「銀行業」、「保険業」、「不動産業」、「サービス業」、「その他金融業」と少なく、その中でも「小売業」に属するコンビニエンスストアーがNoSQLでは難しいように、NoSQLが活躍し得る企業はごく僅かです。もちろん、コンビニエンスストアーに限らず、業務システムにおいて、従来からRDBMSと合わせて用いられているファイルサーバも広義の意味でKVSといえNoSQLいえます。それを昨今いわれる新しいNoSQLで置き換えることはあるかもしれませんが、そのような利用は大騒ぎするほどの問題ではありません。
大学生が就職活動を行うとき、全く違う業界のコンシューマ向け(つまり、TVのCMを流しているような)企業ばかりを志望するという現象がありますが、社会に出ればそんな考え方は「如何に世の中を知らない考え方か」ということが分かると思います。
同じように、NoSQLが活躍し得る企業は目立ちます。特にネット上では突出して目立ちます。だから、「これからはNoSQLだ!」ってなってしまう技術者はどうかと思う。既に「中の人」になっているにもかかわらず、考え方が学生と変わらない。
現在、名前が挙がっているだけでNoSQLは数十種類ありますが、日本の上場企業で考えるとNoSQLが活躍し得る企業の数とあまり変わらない。そんなものに振り回されて足下の技術がおろそかになるなら技術者とは呼べない。もちろん、今、切実にNoSQLに取り組まなくてはならない問題を抱えているなら別ですが。
WEBサービスも最初はSQLで!?
Twitterも、当初は簡単に作れるSQLを採用してました。
最初からスケールアウトを気にして作っても、スケールアウトが必要になる時期はムーアの法則で延びていきます。現在のハード環境であれば、RDBMSで立ち行かなくなるのは、システムにもよりますがユーザ数が数十万人を超えたあたりでしょう。
そのユーザ数のピークが来たときに、それだけのアクセスがあれば投資も融資も集まりますから、リプレースする費用が出せないということはありませんし、実際に、数十万人を超えるサービスに育つ可能性は1%もありません。
それならば、スケールアウトなど気にしないで、如何に良いサービスを早く出せるかに拘った方が現実的でしょう。
Twitterが証明しているように、ウケるサービスを作るために重要なのはタイミングとコンセプトであって、内部構造の技術などどうでもよいのです。
逆にいうと、内部構造の技術などどうでもよいので、WEBサービスの会社なら、SQLができないのに無理にRDBMSを使う必要はありません。個人的に「MySQLを使うならNoSQLの方が良いのでは?」と考えています。
それでも、決済部分はRDBMSを使うべきです(決済部分はアウトソースしても良いですけどね)。
WEBサービスでも PostgreSQL・SQLServer・Oracle・DB2 を使うのであれば、ユーザインターフェースを先に作ることができ、データベースと完全に疎結合にするためにストアドプロシージャを利用するメリットはあります。「ストアドプロシージャを利用するメリットなんてない」と思うのは、昔のOracleが植え付けた「ストアドプロシージャはバッチのためにある」という文化のせいなのです。
そんな迷信に惑わされることなく、是非、サンプルをダウンロードして考えてみてください。