🎓 レベル:標準 | 重要度:A(必須)
📎 前提:リレーショナルモデルと正規化・スタースキーマと次元モデリング | 関連:列指向ストレージと分析クエリ
要点(BLUF)
- 正規化=更新に強い(事実が1箇所・整合性が保てる)/読み取りは遅い(JOINが増える)。非正規化=読み取りが速い(JOIN不要)/更新に弱い(冗長で不整合のリスク)。
- 原則は OLTP(更新系・トランザクション)は正規化、OLAP(分析系・集計)は非正規化。両者は要件が逆なので、同じデータでも目的別に持ち方を変える。
- 判断軸はシンプル:「書き込みが多いか、読み取りが多いか」と「どんなクエリで使うか」。迷ったら正規化から始め、計測して遅い所だけ非正規化する。
概念 ── 同じ事実、逆向きの最適化
正規化と非正規化は「どちらが正しいか」ではなく、何を最適化するかの違いです。
flowchart LR
N["正規化"] -->|得意| NW["更新の整合性・書き込み効率"]
N -->|苦手| NR["多段JOINで読み取りが遅い"]
D["非正規化"] -->|得意| DR["JOIN不要で読み取りが速い"]
D -->|苦手| DW["冗長・更新時異常のリスク"]
更新が主の業務システム(受発注・在庫)は、整合性が命なので正規化。分析・レポートは読み取りが主で更新が少ないので、JOINを減らす非正規化(スタースキーマ)が有利です。
設計の勘所 ── OLTP と OLAP
| 観点 | OLTP(更新系) | OLAP(分析系) |
|---|---|---|
| 主な操作 | 1行のINSERT/UPDATE | 大量行のSUM/GROUP BY |
| 設計 | 正規化(3NF) | 非正規化(スタースキーマ) |
| 最適化対象 | 書き込みの整合性・速さ | 読み取り・集計の速さ |
| 例 | 注文登録・在庫引当 | 月次売上ダッシュボード |
| ストレージ | 行指向 | 列指向(→ 列指向ストレージと分析クエリ) |
現代データスタックでは、OLTPの正規化データを取り込み、変換段で分析用に非正規化(次元モデル化)してDWHに置くのが定番の流れです。つまり両方を、パイプラインの上流/下流で持ち分けます。
なぜそうするか ── 計測してから崩す
なぜ「まず正規化」が安全なのか。非正規化は取り返しが付きにくいからです。冗長を入れると、更新ロジック・整合性チェックが各所に散らばり、後から正規化に戻すのは大仕事。逆に、正規化を起点にして「このクエリだけ遅い」と計測で特定し、その箇所だけ集計済みテーブル(マテリアライズドビュー等)で非正規化する方が、リスクを局所化できます。
「推測するな、計測せよ」。早すぎる非正規化は、性能問題が実在する前に整合性リスクを買う行為です。
⚠️ よくある落とし穴
- 速さを期待して最初から全部非正規化 → 更新時異常が頻発し、データの信頼が崩れる。性能は計測してから対処。
- OLTPのDBで重い分析クエリを直接回す → 本番更新を圧迫する。分析は**別系(DWH)**へ分離(→ データウェアハウス)。
- 「非正規化したのに速くならない」→ 行指向DBのまま集計しているのが原因のことも。列指向(→ 列指向ストレージと分析クエリ)が効く場合がある。
対応ラボ
なし(判断軸の回)。正規化の更新時異常は リレーショナルモデルと正規化、非正規化の集計は スタースキーマと次元モデリング のラボで確認済み。
関連
- 起点となる正規化は リレーショナルモデルと正規化、分析向け非正規化は スタースキーマと次元モデリング
- 非正規化の読み取りをさらに速くする物理形式は 列指向ストレージと分析クエリ
- OLTPとOLAPを物理的に分ける受け皿は データウェアハウス