コンピューターサイエンス:アルゴリズム / OS / ネットワーク / DB
RDB と NoSQL の違い
「あとで結合したい」と言い出したときには遅い
EC サイトを MongoDB で作ったとします。利用者の文書の中に、その人の注文をそのまま配列で埋め込んでおく。マイページの表示は文書を 1 つ読むだけで終わり、当然速い。ここまでは気持ちよく進みます。
半年後、「商品ごとの売上を出したい」と言われます。売上は各利用者の文書の奥にばらばらに埋まっているので、全利用者を読み、注文を取り出し、商品ごとに足し上げるしかありません。最初に決めた「1 人分をひとかたまりで持つ」という形が、新しい問い合わせ方をそのまま拒んでいます。
作り直すのは持ち方だけではありません。すでに入っている数百万件の文書を、新しい形へ全部書き換える移行も必要になります。
分けて持つか、まとめて持つか
RDB は逆の選択をしています。利用者と注文と商品を別々の表に分け、同じ事実は 1 か所にだけ置く。読むときに結合して組み立て直します。取り出し方を先に決めなくてよい代わりに、1 回の読み取りで複数の表を触ります。
NoSQL は、取り出す形のまま保存します。読み方が 1 通りに決まっているなら圧勝ですが、読み方が増えると持ち方から作り直すことになります。
どちらが正しいという話ではありません。決めているのは「同じ事実を何か所に置くか」の一点です。1 か所に置けば書き換えは 1 回で済み、読むたびに集める手間がかかる。使う場所ごとに置けば読むのは一瞬で、書き換えは置いた数だけ発生する。それだけのことです。
| 観点 | RDB | NoSQL |
|---|---|---|
| 持ち方 | 表に分けて、読むときに結合 | 読む形のまま 1 かたまりで保存 |
| 事実の置き場所 | 1 か所だけ | 使う場所ごとに複製されやすい |
| 想定外の集計 | 後から書ける | 全件読み直しになりやすい |
| 台数を増やす | 手間がかかる | 前提として設計されている |
NoSQL と一口に言っても中身は別物です。キーと値だけの単純な倉庫、JSON 文書をそのまま入れるもの、書き込み量に振り切ったもの、関係そのものを辿るもの。共通しているのは「RDB の何かを捨てて、代わりに何かを得た」という点だけです。選ぶときに見るべきなのは名前ではなく、その製品が何を捨てたかです。
速いから NoSQL、ではない
「NoSQL は速い」はよくある誤解です。速いのは、そのデータの持ち方に合った読み方をしたときだけで、合わない読み方をすれば結局は全件を読みます。
「スキーマがない」も正確ではありません。DB の側に定義がないだけで、アプリのコードの中には必ず暗黙の形があります。定義が DB に書いていない分、形が少しずつずれた文書が混ざっても誰も止めてくれません。3 年前に入れた文書だけ項目名が違う、という事故はこうして起きます。
「トランザクションが使えない」も古い認識で、複数の文書にまたがる操作を扱える製品は増えています。ただし、分散した状態でそれを使うと速さの利点を自分で削ることになります。結局のところ、何を諦めた製品なのかを知らずに選ぶと痛い目を見ます。
「とりあえず NoSQL」で始めて、結合したくなって作り直す失敗は本当に多いです。
現実的な線引きはこうなります。整合性が要る業務データは RDB。セッションやキャッシュのように、読み方が 1 通りで消えても作り直せるものはキーと値の倉庫。ログや解析のように、書き込みが膨大で 1 台に収まらないものは、そこだけ別の DB を足す。多くのサービスは RDB 1 本で始めて、必要になった部分だけを外に出す形に落ち着きます。