発展正規化

非正規化とパフォーマンスの実務判断

定義

非正規化 (denormalization) とは、参照性能や運用容易性を優先し、正規化により分割されたリレーションを意図的に冗長化または結合統合する設計手法であり、更新時異常のリスクと引き換えに読み取り効率を得る。

正規化した後にわざと崩す?

第3正規形 まで進めれば、 マスタが独立したテーブルに分かれて更新時異常が消える。 その代わり、データを取り出すときには複数のテーブルを結合 (JOIN) する必要がある。 テーブルが増えるほど JOIN も増える。

非正規化 は、この JOIN のコストが実運用で問題になった時に、 あえて「正規化した状態を一部だけ崩す」設計手法。 「わざと同じ情報を複数の場所に書く」ことで JOIN を減らし、読み取りを速くする。 代わりに更新時異常のリスクは戻ってくるので、それを別の仕組み (トリガー / アプリ側ロジック) で防ぐ責任も負う。

非正規化を選ぶ動機は主にこの 3 つ:

  • JOIN 回数を減らしたい: 一つの参照でいくつものテーブルを JOIN する必要がある画面で、 関連情報を親テーブルにコピーしておいて JOIN を減らす。
  • 読み取りが圧倒的に多い: 記事の閲覧数のように「読まれるのが多くて、書き換えは少ない」データでは、 読み取り時のシンプルさを優先する。
  • 集計値の再計算が重い: リアルタイムに COUNTSUM を毎回計算するコストが高いなら、 事前に集計した数字を保存しておく。

典型例: 記事とコメント数

3NF → 非正規化 (集計値の埋め込み)
Before
記事
記事IDPKタイトル投稿日
A001SQL入門2026-06-01
A002インデックス設計2026-06-15
After
記事 (非正規化)
記事IDPKタイトル投稿日コメント数
A001SQL入門2026-06-0123
A002インデックス設計2026-06-1545
「コメント数」は本来 コメント テーブルから COUNT(*) で毎回集計するのが正規化された姿。 しかし記事一覧を大量表示する画面ではその集計が重荷になる。 そこで 記事 テーブルに コメント数 列を持たせ、コメント追加/削除のたびに更新する。

この場合、更新時異常のリスクは「コメントを追加/削除した時に必ずコメント数を +1/-1 する」ことを アプリケーション層またはトリガーで保証することで吸収する。

「参照が遅い」時にまず試すのはインデックス

「参照が遅い」を解決する手段は非正規化だけではない。むしろ最初に試すのはインデックス側での対処で、 テーブル構造を触らずに済むぶん影響範囲が小さくて安全。

  • カバリングインデックス: SELECT で欲しい列を全部インデックスに含めれば、テーブル本体を読まずに済む。単一テーブルの検索ならたいていこれで足りる。
  • 複合インデックス: JOIN で使う外部キー列に複合インデックスを貼るだけで JOIN のコストが劇的に下がることも多い。
  • クラスタ化インデックス: テーブルの物理配置を主キー順にすることで、レンジ検索の I/O を減らせる。

これらを試した上でなお足りない、かつ更新側のコストも含めて総合的に得だと判断できる時に、 初めてテーブル構造の非正規化に踏み込むのが安全な順序。

非正規化の中間解: 本体テーブルは正規化のまま、参照用の別テーブルを作る

「本体テーブルは正規化のまま維持しつつ、参照専用の別テーブルを冗長に持つ」というやり方もある。 こちらは本体の更新時異常リスクを触らずに済むので、非正規化の中では比較的安全。

  • マテリアライズドビュー: JOIN や集計の結果を実体としてキャッシュしたもの。 即時更新か定期更新か、DBMS が用意する仕組みに乗って整合を保てる。
  • サマリテーブル: 集計結果を専用のテーブルに保存し、バッチや ETL で定期的に更新する。 分析用途で多用される。

非正規化するかどうかの判断手順

  1. まずは 3NF まで正規化 する (これが基本形)
  2. 実際の参照パスで EXPLAIN を取って、本当にどこが遅いのかを特定する
  3. インデックス側で解決 できないか検討する (カバリング / 複合)
  4. マテリアライズドビュー / サマリテーブルで解決できないか検討する
  5. それでも足りない場合に、限定した箇所で非正規化 (列の冗長化) を検討する
  6. 非正規化するなら、整合を保つ仕組み (トリガー / アプリ側ロジック / バッチ検証) を必ずセットで用意する

よくある疑問

Q.非正規化はいつやるべきですか?
A.読み取りの頻度と結合コストが更新頻度を大きく上回り、かつ更新時異常を運用や制約で吸収できる見込みがある時です。まず正規化した上で計測してから判断します。
Q.非正規化とカバリングインデックスの違いは?
A.非正規化はテーブル構造自体を冗長化する設計変更、カバリングインデックスはテーブル本体はそのままに参照高速化のためインデックスに列を含める手法です。多くのケースでインデックス側で解決できます。
Q.正規化しすぎるとどうなる?
A.参照時に多くの JOIN が必要になり、実行計画が複雑化してオプティマイザが失敗しやすくなります。ただしまず正規化してから必要な部分だけ崩す方が安全です。
Q.マテリアライズドビューは非正規化ですか?
A.広義には非正規化の一種と言えます。ただしテーブル本体は正規化したまま、参照用の別実体を持つため、更新時異常のリスクを局所化できる利点があります。

関連トピック

もっと学びたい方へ(おすすめ書籍)

本セクションはAmazonアソシエイトのリンクを含みます。

オンライン個別指導

もっと深くDBを学びたい方へ。

たいてっくが、SQL・データベース設計・パフォーマンスチューニング・ IPAデータベーススペシャリスト対策まで、1対1で学習をサポートします。まずは無料相談から。

無料相談を予約する →