変更要約: 初版
5.3データベース方式設計
トランザクション整合性を重視するRDBとスキーマ柔軟性/水平拡張を重視するNoSQLの選択、読み取り性能とデータ保全を両立するレプリケーション、書き込みスループットを水平分割で高めるシャーディング、そしてキャッシュによる性能改善と整合性の緩和の判断を学びます。
システムアーキテクトは、データの特性(構造の定まり方・整合性要求)とアクセス特性(読み取り/書き込みの比率・データ量の増え方)から、適切なデータベース方式と拡張手段を選ぶ必要があります。単に「流行っているから」ではなく、整合性要求とスケール要求のどちらを優先するかという軸で判断することが実務では求められます。
5.3.1RDBとNoSQLの選択
- RDB(リレーショナルデータベース)=あらかじめ定義したスキーマに基づき表形式でデータを管理し、ACID特性(原子性・一貫性・独立性・永続性)に基づくトランザクションで強い整合性を保証する。複数テーブルにまたがる整合性(例:注文と在庫の同時更新)が要求される業務システムに適するが、スキーマ変更のコストが高く、単一ノードでの垂直スケールが限界に近づくと水平方向の拡張が難しいという制約がある。
- NoSQL=スキーマを厳密に固定せず(キーバリュー型・ドキュメント型・カラム指向型・グラフ型等)、多くの実装は複数ノードへの水平分散を前提に設計されている。厳密なACID特性よりBASE特性(結果整合性を許容してでも可用性とスケーラビリティを優先)を志向する製品が多く、大量データ・高頻度アクセス・スキーマが流動的な要件(例:ログデータ、商品カタログ、セッション情報)に適する反面、複数レコードにまたがる強い整合性の保証は苦手とする実装が多い。
- 選択の判断軸は「複数エンティティにまたがる強い整合性が業務上必須か」対「データ量/アクセス量の水平拡張が優先か」。決済や在庫のように整合性を欠くと業務上致命的な領域はRDB、大量のログや行動履歴のように整合性より書き込みスループットと拡張性を優先すべき領域はNoSQL、というように同一システム内でも領域ごとに使い分ける(ポリグロットパーシステンス)のが実務的である。
5.3.2レプリケーションとシャーディング
- レプリケーション=同一データを複数のノード(レプリカ)に複製して保持する仕組み。代表的にはプライマリ(更新を受け付ける)とレプリカ(プライマリの複製を保持し主に読み取りに使う)を分ける構成で、読み取り負荷を複数ノードに分散しつつ、プライマリ障害時にはレプリカへフェイルオーバーしてデータ保全と可用性を高める。ただし各ノードが同じデータの複製を持つため、書き込みスループットそのものは複製先の数だけ増えるわけではない(むしろ複製の伝搬コストがかかる)。
- シャーディング(水平分割)=1つの大きなデータ集合を、特定のキー(例:顧客IDのレンジやハッシュ値)に基づいて複数の独立したノード(シャード)に分割して格納する仕組み。各シャードが異なるデータのサブセットを持つため、ノード数を増やすほど全体の書き込み/読み取りスループットとデータ容量を水平に拡張できる。一方、シャーディングキーの選び方を誤ると特定シャードにアクセスが偏るホットスポットが生じたり、複数シャードをまたがる結合・トランザクションが困難/高コストになる設計上の課題がある。
- つまり、読み取り負荷の分散とデータ保全(可用性)が課題ならレプリケーション、書き込みスループットとデータ容量そのものの拡張が課題ならシャーディングという判断軸になる。大規模システムでは両者を組み合わせ、各シャードをさらにレプリケーションして冗長化することも一般的である。
5.3.3キャッシュと整合性の緩和
- キャッシュ=頻繁に参照されるが更新頻度の低いデータを、本体のデータベースより高速にアクセスできる層(インメモリストア等)に一時的に保持し、データベースへの読み取り負荷を削減し応答時間を短縮する仕組み。キャッシュ導入は必然的に「キャッシュ側のデータが本体データベースの最新値と一時的にずれる」という整合性の緩和を伴うため、業務上どの程度のデータの鮮度遅延まで許容できるか(例:在庫数の表示は数秒遅れても許容できるが、決済残高はリアルタイムでなければならない)をアーキテクトが事前に判断し、対象データを選定する必要がある。
「RDB=ACIDで強い整合性・複数テーブルの整合性が必須の業務向き」「NoSQL=水平分散前提・BASE志向・大量/流動的データ向き」「レプリケーション=読み取り分散/可用性・書き込みスループットは増えない」「シャーディング=書き込み/容量の水平拡張・シャーディングキー選定が鍵」「キャッシュ=応答短縮と引き換えに整合性を緩和」が最頻出です。レプリケーションとシャーディングの目的の違い(読み取り分散 対 容量/書き込み拡張)を混同しないこと。
あるシステムアーキテクトが、急成長中のECサイトのデータベース基盤を再設計する場面を想定します。まず商品カタログと在庫・注文データの性質を分析したところ、注文と在庫は同一トランザクション内で整合性が崩れると二重販売等の業務上致命的な問題になるため、この領域は強い整合性を保証できるRDBを維持する判断をしました。一方、アクセスログや商品閲覧履歴はデータ量が膨大でスキーマも流動的、かつ多少の遅延や結果整合性は業務上許容できるため、この領域には水平分散を前提としたNoSQLを採用しポリグロットパーシステンスの構成にしました。次に、注文データを持つRDBへの読み取りアクセス(商品ページの閲覧等)が急増し読み取りがボトルネックになっていることが判明したため、プライマリの更新性能を損なわずに読み取りを複数ノードへ分散する目的でレプリケーションを導入し、参照系のクエリをレプリカへ振り分けました。さらにその後、セール時に書き込み(新規注文)そのものが単一プライマリの処理能力を超え始めたことが判明したため、今度はレプリケーションでは解決できない課題(書き込みスループットそのものの限界)と判断し、顧客IDをキーに複数ノードへ注文データを分割するシャーディングの導入を検討しました。その際、単純な連番の顧客IDをそのままシャーディングキーにすると新規顧客が特定のシャードに集中するホットスポットが生じる懸念があったため、ハッシュ化したキーで分散させる設計に見直しました。最後に、商品ページで頻繁に参照される「在庫あり/なし」の表示は、数秒程度の遅延が生じても業務上問題ないと業務部門と合意できたため、キャッシュ層を導入してデータベースへの参照負荷をさらに軽減しました。このように、整合性が必須の領域はRDB、読み取り負荷の分散はレプリケーション、書き込み/容量の限界にはシャーディング、遅延許容な参照はキャッシュ、と課題の性質ごとに手段を使い分けることが、データベース方式設計の核心です。
| 手段 | 主目的 | 効かない/向かない課題 |
|---|---|---|
| レプリケーション | 読み取り分散・可用性(フェイルオーバー) | 書き込みスループットの水平拡張には効かない |
| シャーディング | 書き込み/容量の水平拡張 | シャーディングキー次第でホットスポット/シャード跨ぎ結合の困難が残る |
| キャッシュ | 応答時間短縮・DB参照負荷削減 | 鮮度が業務上許容できないデータには不向き |
ひっかけ: 「読み取りが遅いのでレプリケーションを増やせば書き込みスループットも上がる」は誤りです——レプリケーションは読み取り分散と可用性が目的で、各ノードが同じデータの複製を持つため書き込みスループットの水平拡張には寄与しません。書き込み/容量の限界にはシャーディングが必要です。また「NoSQLは常にRDBよりスケーラブルで優れている」も誤り=複数エンティティにまたがる強い整合性が業務上必須な領域(決済/在庫の同時更新等)ではRDBの方が適切であり、単純な優劣ではなく要件で選びます。
5.3.4この節のまとめ
- 複数エンティティにまたがる強い整合性が必須ならRDB、水平分散/大量流動データが優先ならNoSQL(ポリグロットパーシステンスも実務的)
- 読み取り分散/可用性の課題にはレプリケーション、書き込み/容量拡張の課題にはシャーディング(キー選定でホットスポット回避)
- キャッシュは応答短縮と引き換えに整合性を緩和=業務上許容できる鮮度遅延の範囲で対象データを選ぶ
進捗の記録にはログインが必要です。
理解度チェック
(軽い確認用)Q1. ECサイトの注文と在庫データは、同一トランザクション内で整合性が崩れると二重販売という業務上致命的な問題になる。このデータ領域のデータベース方式として最も適切な判断はどれか。
Q2. 注文データを持つRDBへの読み取りアクセス(商品ページ閲覧等)が急増し読み取りがボトルネックになっている。プライマリの更新性能を損なわずにこの課題へ対処する最も適切な手段はどれか。
Q3. 前問のレプリケーション導入後、セール時に新規注文の書き込みそのものが単一プライマリの処理能力を超え始めた。顧客IDをキーにシャーディングを検討する際、単純な連番の顧客IDをそのままシャーディングキーにすると生じうる懸念として最も適切なものはどれか。

