リレーショナルデータベースとNoSQLデータベース:システムに適した基盤の選び方
The choice between a relational and a NoSQL database is one of the most consequential architectural decisions you'll make. Get it right and your system scales gracefully. Get it wrong and you'll be fighting your database for years. This is what you actually need to know.
どのデータベースもデータを格納します。しかし、共通点はそれだけです。リレーショナルデータベースとNoSQLデータベースは、データの構造化、格納、およびクエリの実行方法について、根本的に異なる哲学を体現しており、その違いは、それらを基盤として構築されたシステムのあらゆる層に波及しています。
これは、古い対新しい、あるいは単純対高度といった問題ではありません。どちらのカテゴリーにも、実戦を経て成熟し、膨大な規模で運用されているシステムが存在します。重要なのは「目的に適合しているか」という点です。つまり、どのモデルが、あなたのデータの形状、アプリケーションのアクセスパターン、そしてユーザーが求める一貫性の保証に合致するかということです。
リレーショナルデータベースとは何か
リレーショナルデータベースは、データをテーブル(行と列、およびそれらの間に明示的に定義された関係)として整理します。名称にある「リレーショナル(関係)」という言葉は、テーブル同士が関連しているという事実(実際に関連していますが)を指すのではなく、数学的な概念である「関係(relation)」、すなわち同じ属性を共有するタプルの集合を指しています。 1970年にIBMのエドガー・コッドによって確立されたこの理論的基盤は、驚くほど長きにわたりその有効性を証明してきました。
リレーショナルデータベースの中核となる特徴は以下の通りです:
固定スキーマ。 データを挿入する前に、構造を定義します。つまり、どのテーブルが存在するか、各テーブルにどの列があるか、各列がどのデータ型を受け入れるか、そしてどの制約が適用されるか(NOT NULL、UNIQUE、CHECKなど)を定義します。スキーマは、アプリケーションとデータベース間の契約です。
正規化。 データは冗長性を排除するように整理されます。顧客の名前は、customersテーブルに一度だけ登場します。すべての注文は、IDによってその顧客を参照します。名前が変わった場合、変更は一箇所で行われます。これは単なる整理整頓ではなく、一貫性を保証するものです。
ACIDトランザクション。 原子性(Atomicity)、一貫性(Consistency)、隔離性(Isolation)、耐久性(Durability)。トランザクションは完全に完了するか、まったく完了しないかのいずれかです。ある口座から別の口座へ送金する場合、引き落としの処理と入金処理は同時に実行されるか、どちらも実行されません。データベースはエンジンレベルでこれを強制します。
SQL。 構造化問い合わせ言語(Structured Query Language)は、リレーショナルデータベースのための普遍的なインターフェースです。これは宣言型であり——「何を」得たいかを記述し、「どのように」得るかは記述しません——極めて表現力に富んでいます。 結合、集計、ウィンドウ関数、サブクエリ、CTE:SQLの全機能を活用すれば、その処理を行うためのアプリケーションコードを記述することなく、データに対して複雑な質問を投げかけるためのツールが得られます。
主要なリレーショナルデータベース(PostgreSQL、MySQL、SQL Server、Oracle)は、具体的な機能セット、パフォーマンス特性、ライセンスモデルは異なるものの、これらの特性を共有しています。特にPostgreSQLは、厳格な標準準拠と卓越した機能セットを兼ね備えており、新規プロジェクトにおけるデフォルトの選択肢となっています。
NoSQLデータベースとは何か
「NoSQL」は、いくつかの異なるデータベースカテゴリを包括する総称であり、主に「何ではないか」という点で共通しています。つまり、リレーショナルではなく、SQLを主要なインターフェースとして使用しない(ただし、SQLに似たクエリ言語をサポートするものもあります)ということです。 この用語は「SQLだけではない(not only SQL)」と理解するのが適切であり、リレーショナルモデルだけが唯一の有効なアプローチではないという認識を表しています。
主なNoSQLのカテゴリーは以下の通りです:
ドキュメントデータベースは、データをドキュメント(通常はJSONやBSON)として保存します。各ドキュメントは異なる構造を持つことができます。MongoDBが最も広く使用されており、その他にはCouchDBやFirestoreなどがあります。テーブルも固定スキーマも存在せず、ドキュメントの「コレクション」には、全く異なるフィールドを持つレコードが含まれることがあります。
キーバリューストアは最もシンプルなモデルです。すべてのレコードは、一意のキーで参照可能な値です。Redisが代表的な例であり、キャッシュ、セッションストレージ、リアルタイムのリーダーボードなどで広く利用されています。DynamoDBも主にキーバリューストアとして動作しますが、その上にドキュメント機能が追加されています。
カラムファミリーストアは、データを行単位ではなく列単位で整理するため、数百万行に及ぶデータの中から特定の列を極めて効率的に読み出すことが可能です。Apache CassandraやHBaseが代表的な例です。このモデルは、クエリパターンが事前に分かっている、書き込みが頻繁で処理量が多いワークロード向けに設計されています。
グラフデータベースは、データをノードとエッジ(エンティティとそれらの間の関係)としてモデル化します。Neo4jが代表的な例です。エンティティ間の関係がクエリの主な対象となる場合(ソーシャルネットワーク、レコメンデーションエンジン、不正検知など)、グラフデータベースは、深く再帰的なSQLを必要とするようなクエリを、自然な形で表現することができます。
時系列データベースは、時間軸でインデックス付けされたデータ向けに最適化されています。InfluxDB、TimescaleDB、Prometheusなどが挙げられます。センサーの計測値、金融市場のティックデータ、アプリケーションのメトリクスなど、タイムスタンプが常に主キーであり、時間軸にわたる範囲クエリが主なアクセスパターンとなるデータが対象です。
他のすべてを左右する構造的な違い
リレーショナルデータベースとNoSQLデータベースの最も根本的な違いは、構文やスケールではなく、データ構造とクエリの柔軟性の関係にあります。
リレーショナルデータベースは、設計段階でのスキーマの厳格さを代償として、最大限のクエリの柔軟性を提供します。データは正規化され、型付けされているため、クエリ実行時にほぼあらゆる質問を投げかけることができます。 スキーマ設計時には予想もしなかった方法でテーブルを結合することも可能です。初期設計から数ヶ月後に追加したディメンションを横断して集計することもできます。スキーマはデータを制約しますが、クエリ言語は自由をもたらします。
NoSQLデータベースは、これとは逆のトレードオフを行います。データの構造化や記述方法における柔軟性を提供する代わりに、クエリパターンはより制約されます。ドキュメントデータベースでは、移行作業なしにどのような形状のデータでも格納できます。しかし、ドキュメント間で効率的にクエリを実行するには、アクセスパターンを事前に把握し、それに合わせてデータ構造を設計する必要があります。
これが核心となるジレンマです:スキーマの柔軟性対クエリの柔軟性。両方を手に入れることは可能ですが、それはある程度に限られます。選択するデータベースモデルは、そのユースケースにおいてどちらのトレードオフがより許容できるかを反映したものです。
CAP定理とその重要性
分散システムは、一貫性(Consistency)、可用性(Availability)、パーティション耐性(Partition Tolerance)の3つを同時に保証することはできず、せいぜい3つのうち2つしか達成できません。これがCAP定理であり、障害発生時にリレーショナルデータベースとNoSQLデータベースの挙動が異なる理由を理解するための理論的基盤となっています。
リレーショナルデータベースは、伝統的に一貫性とパーティション耐性を優先します。すべての読み取り操作は、最新の書き込み内容を反映します。ネットワークのパーティションが発生し、データベースが一貫性を保証できなくなった場合、古いデータを返すことを拒否します。つまり、データが不正になるのではなく、利用不可となるのです。
多くのNoSQLデータベース(特にCassandraやDynamoDBのような水平分散向けに設計されたもの)は、可用性とパーティション耐性を優先します。これらはネットワークパーティションが発生している間でもデータを提供し、一部の読み取り操作で古い値が返される可能性があることを容認します。 これが「最終的な一貫性(eventual consistency)」です。すべてのノードは最終的に同じ値に収束しますが、それまでの間、値が一致しない期間が存在します。
実用上の意味:銀行残高、在庫数、医療記録など、アプリケーションが古いデータの読み取りを絶対に許容できない場合は、強い一貫性が必要です。 一方、ソーシャルメディアのフィード、製品カタログ、ユーザープロファイルなど、常に利用可能であることと引き換えに、一時的な不整合を許容できるアプリケーションであれば、最終的な一貫性で十分であり、アーキテクチャの自由度が高まります。
実例:適切な選択が結果に差をもたらしたケース
GitHub:グローバルプラットフォームの中核にあるPostgreSQL
GitHubは、PostgreSQL上で世界最大級のソフトウェアコラボレーションプラットフォームを運用しています。そこには数百万のリポジトリ、数十億のイベント、そしてユーザー、組織、リポジトリ、プルリクエスト、イシュー、コメントを横断する複雑なリレーショナルクエリが存在します。 リレーショナルモデルはこのドメインに適合しています。これらのエンティティ間の関係こそが製品そのものだからです。プルリクエストはリポジトリに属し、ユーザーによって作成され、他のユーザーによってレビューされ、イシューをクローズし、CIパイプラインをトリガーします。
長年にわたり、GitHubは読み取りレプリカを備えた単一のプライマリPostgreSQLインスタンスを運用していました。スケールが拡大するにつれ、Vitess(一部のワークロード向けのMySQLシャーディングレイヤー)や接続管理のためのProxySQLを導入しましたが、リレーショナルなコアは維持されました。 ここから得られる教訓は、PostgreSQLが努力なしに無限にスケールするという点ではありません。関係性によって定義されるドメインに対してリレーショナルモデルが最適であり、異なるデータモデルへの移行の方がコストがかさむため、そのスケールに投資した努力は正当化されたということです。
Twitter:MySQLから混合アーキテクチャへの苦難の移行
TwitterはMySQLでスタートしましたが、ユーザー数の増加が単一のリレーショナルデータベースの処理能力を上回り、よく知られたスケーリングの危機に直面しました。 核心的な問題は、ソーシャルグラフ(数億人のユーザー間のフォロワー/フォロー関係)と、タイムラインのファンアウト問題でした。つまり、1,000万人のフォロワーを持つユーザーがツイートすると、そのツイートは1,000万のタイムラインにほぼ瞬時に表示される必要があるのです。
Twitterが実装していたリレーショナルモデルでは、この書き込みのファンアウトを要求される速度で処理することができませんでした。Twitterはソーシャルグラフをカスタムインメモリストアに移行し、最終的にはタイムライン用にManhattan(社内開発の分散型キーバリューストア)、その他の高書き込み負荷ワークロード用にCassandraを採用しました。
ここでの教訓は微妙なニュアンスを含んでいます。Twitterのコアデータ(ツイート、ユーザー、関係性)は、根本的にリレーショナルな性質を持っています。問題はデータモデルそのものではなく、分散処理を必要とする規模での書き込み量とファンアウトにありました。この移行はコストがかかり、技術的にも複雑で、何年にもわたるエンジニアリングへの投資を必要としました。 Twitterの規模においては、それは正しい判断でした。しかし、他のほぼすべてのアプリケーションの規模においては、時期尚早だったでしょう。
MongoDB:スキーマの柔軟性に関する教訓
2010年代初頭、MongoDBの人気が急速に高まる中、多くのチームが主にそのスキーマの柔軟性——事前にスキーマを定義せずにデータ保存を開始できる点——を理由にMongoDBを採用しました。プロトタイピングや初期段階の開発においては、これが確かに反復開発を加速させました。
問題は、システムが成熟するにつれて現れました。スキーマの強制がないため、データの不整合が徐々に蓄積していきました。必須であるべきフィールドが欠落していることがありました。整数であるべき値が文字列になっていることもありました。一貫した構造を前提としたクエリが、予期しない結果を返すこともありました。チームは、本来ならデータベースが自動的に強制してくれたはずの検証を、アプリケーションレベルで大規模に記述せざるを得なくなりました。
これは、データベースとしてのMongoDBの失敗ではありません。多くのユースケースにおいて、MongoDBは適切なツールです。これは、「スキーマの柔軟性は無条件に良い」という前提の失敗なのです。柔軟性は、データ構造について考えるというコストを先送りしただけであり、そのコストを排除したわけではありません。 規律なくMongoDBを使用したチームは、リレーショナルデータベースが提供したであろう保証なしに、アプリケーションコード内でリレーショナルスキーマの貧弱なバージョンを実装することになってしまいました。
Amazon DynamoDB:適切なユースケースにおける成功事例
Amazonのショッピングカートは、NoSQLが正しく活用された典型的な例の一つです。 要件は明確だった。ショッピングカートは常に利用可能でなければならない(地域的な障害が発生している間でも、顧客は常に商品を追加できる必要がある)、膨大な書き込み量(数億人のユーザーが商品を追加・削除する)を処理できなければならない、そしてアクセスパターンは単純で事前に把握されている(常に顧客IDによるアクセス)必要があった。
DynamoDBの着想源となった2007年の論文で、Amazonのエンジニアリングチームは、ショッピングカートに「最終的な一貫性(eventual consistency)」を意図的に採用したことを説明しています。つまり、ネットワークの分割中に2台のデバイスが同時に商品を追加した場合、たとえ一時的にわずかに一貫性のない状態が表示されることになっても、分割が解消された際には両方の追加が保持されるという仕組みです。 たとえ一時的な不整合を犠牲にするとしても、常に書き込み可能なショッピングカートは、時折利用できないカートよりも価値が高いのです。
このユースケース(単純なキーバリューアクセス、既知のクエリパターン、一貫性よりも可用性を優先)を軸にしたDynamoDBの設計こそが、その優れた点です。DynamoDBを汎用リレーショナルデータベースとして扱い、複数のエンティティにまたがる複雑なクエリを実行しようとするアプリケーションは、常に困難に直面します。
Airbnb:検索にはElasticsearch、データ管理にはPostgreSQL
Airbnbの検索機能(場所、日程、価格、設備、空き状況によるリスティングのフィルタリング)は、リレーショナルデータベースでは大規模な環境で効率的に処理できないクエリです。 地理的な検索、全文検索、そして数百万件のリスティングにわたる複雑な多属性フィルタリングの組み合わせは、まさにElasticsearchが設計されたユースケースそのものです。
Airbnbは、Elasticsearchを検索レイヤーとして使用しつつ、PostgreSQLをシステム・オブ・レコードとして維持しています。 リスティングが更新されると、その変更はPostgreSQL(完全なACID保証を備えた「真実の源」)に書き込まれ、その後、非同期的にElasticsearch(検索体験の特定のクエリパターンに最適化された検索インデックス)に伝播されます。
これは成熟したアーキテクチャパターンです。つまり、それぞれの目的に適したデータベースを使用し、明確な「真実の源」を維持しつつ、複数のストアを同期させるという運用上の複雑さを受け入れるというものです。境界線が明確であり、トレードオフが理解されているからこそ、このアプローチは機能するのです。

リレーショナルデータベースを選ぶべき場合
リレーショナルデータベースは、ほとんどのアプリケーションにとって最適なデフォルトの選択肢です。明らかにリレーショナルデータベースが適しているケースは以下の通りです:
データ間に意味のある関係性がある場合。 システム内のエンティティ(ユーザーとその投稿、注文とその明細、プロジェクトとそのタスクなど)が重要な関係性で結びついている場合、リレーショナルモデルはその関係性を直接的に表現し、それらを横断して効率的にクエリを実行できるようにします。
強力な一貫性が必要な場合。 金融取引、在庫管理、予約システム、医療記録など、誤った読み取りが現実的な影響を及ぼす領域では、ACID保証が不可欠です。リレーショナルデータベースは、エンジンレベルでこれを提供します。
クエリのパターンが完全に把握できていない場合。 設計段階で完全に予測できないデータに関する質問にアプリケーションが答える必要がある場合、SQLの柔軟性は貴重です。適切に正規化されたスキーマに対してアドホックなクエリを作成できる能力は、運用上の大きな強みとなります。
チームがSQLを習得している場合。 これは些細なことのように聞こえるかもしれませんが、そうではありません。SQLはソフトウェアエンジニアリングにおいて最も広く理解されている技術スキルのひとつです。採用する開発者は皆、ある程度はSQLを理解しています。インデックスの追加方法、クエリプランの読み方、バックアップの管理方法といった運用知識は広く入手可能です。ツール群のエコシステムも成熟しています。
**何が必要か確信が持てない場合。**迷ったら、まずはPostgreSQLから始めましょう。実際のアクセスパターンを把握した後で、特化型のストアを導入する方が、データが想定以上に構造化されていた場合にドキュメントストアからリレーショナルモデルへ移行するよりも簡単です。
NoSQLを選ぶべき場合
特定の要件を、過度な労力をかけずにリレーショナルモデルで満たすことができない場合、NoSQLが適切な選択肢となります:
書き込み量が単一ノードの処理能力を超える場合。 地理的に分散したシステム全体で、アプリケーションが毎秒数十万回の書き込みを維持する必要がある場合、多数のノードにわたる水平スケーリングが不可欠になります。Cassandraのようなカラムファミリー型ストアは、このために設計されています。リレーショナルデータベースも分散化は可能ですが、それが本来の動作モードではありません。
データが真にスキーマレスであるか、変動が激しい場合。 製品タイプごとに属性が全く異なる製品カタログ、コンテンツタイプが急速に進化するCMS、イベントスキーマが外部システムによって定義されるロギングシステムなど、データベースによって構造が強制されないドキュメントストアが有効です。
主なアクセスパターンが、大規模なキーバリュー検索である場合。 セッションストア、キャッシュ、リアルタイムのリーダーボード、フィーチャーフラグなど、常に単一のキーでデータにアクセスし、結合や集計を必要としないワークロードでは、キーバリューストアのシンプルさとパフォーマンスが役立ちます。
グラフをモデル化している場合。 主なクエリが関係性の探索(友人の友人をすべて見つける、2つのノード間の最短経路を特定する、循環依存関係を検出するなど)であるなら、グラフデータベースは、再帰的なSQLよりも自然にそれらのクエリを表現し、より効率的に実行できます。
時系列データの最適化が必要である場合。 1秒あたり数百万件のセンサー測定値、金融ティック、またはアプリケーションメトリクスがあり、クエリが主に時間範囲を対象とする場合、タイムスタンプ列を持つリレーショナルストアよりも、専用に設計された時系列データベースの方が適しています。
マルチデータベースの現実
リレーショナルデータベースとNoSQLの比較において理解すべき最も重要な点は、成熟したシステムのほとんどにおいて、これらが「どちらか一方」という二者択一の選択肢ではないということです。大規模なシステムでは、それぞれのワークロードに合わせて選ばれた複数のデータベースが日常的に使用されています。
「システム・オブ・レコード」にはPostgreSQL。セッションキャッシュやレート制限にはRedis。全文検索にはElasticsearch。アプリケーションメトリクスにはInfluxDB。このスタック内の各データベースは、それぞれが最も得意とする役割を果たしており、アプリケーション層がそれら間の整合性を管理しています。
この複雑さがもたらす運用コストは現実的なものです。データベースが1つ増えるごとに、監視、バックアップ、スケーリング、理解すべきシステムが1つ増えることになります。複数のストアの一貫性を保つために必要なエンジニアリングのスキル——例えば、PostgreSQLへの書き込みは成功したが、その後のElasticsearchへの更新が失敗したといった障害シナリオへの対応——は、決して簡単なものではありません。
ほぼすべてのアプリケーションの出発点は、単一のリレーショナルデータベースであるべきです。特定かつ十分に理解された要件を、それなしでは満たせない場合にのみ、特化型のストアを追加してください。時期尚早なデータベースの多様化は、時期尚早な最適化の一種です。つまり、その複雑さが必要かどうかを理解する前に、複雑さを増すことになるのです。

決定を下す
データベースを選択する際に実際に重要な質問:
一貫性に関する要件は何か? 「ユーザーが古いデータを読み取った場合どうなるか」という問いに対する答えが「それは深刻な問題だ」であるなら、ACIDが必要です。答えが「多少面倒だが許容範囲内だ」であれば、選択肢は広がります。
クエリのパターンはどのようなものですか? データへのアクセス方法が正確に把握できており、そのアクセスパターンが単純で処理量が多い場合は、それに最適化できます。アクセスパターンが複雑であるか、完全には把握できていない場合は、SQLの柔軟性が役立ちます。
書き込み量はどの程度ですか? 大多数のアプリケーションにおいて、適切なハードウェア上で適切にチューニングされたPostgreSQLインスタンスであれば、毎秒数千回の書き込みを難なく処理できます。これが真に不十分となるケースは、2010年代のNoSQLブームが示唆していたほど多くはありません。
データの形状はどのようなものですか? 均一性が高く、密接に関連したデータはリレーショナルモデルに適合します。変動が大きく、疎に関連したデータは、ドキュメントモデルの方が適している場合があります。
チームの知識レベルは? 運用上の習熟度が重要です。PostgreSQLを深く理解しているチームであれば、たとえ理論上はNoSQLデータベースの方が適していたとしても、学習中のNoSQLデータベースよりもPostgreSQL上でより信頼性の高いシステムを構築できるでしょう。
リレーショナルデータベースが50年にわたる技術的変遷を生き延びてきたのは、それが常に最良のツールだからではなく、柔軟性、信頼性、理解の深さ、そして数十年にわたる運用ノウハウに裏打ちされた、極めて優れた「デフォルト」だからです。そこから意図的に逸脱する際は、何を得て何を犠牲にするのかを明確に理解した上で判断してください。