Mímisbrunnr知恵の泉

← データエンジニアリング 一覧

🎓 レベル:標準 | 重要度:A(必須)

📎 前提:リレーショナルモデルと正規化ER図とスキーマ設計 | 関連:正規化と非正規化のトレードオフデータウェアハウス

要点(BLUF)

概念 ── 「事実」と「切り口」を分ける

分析の問いはたいてい「何を(指標)/どの切り口で見たいか」の形です。「売上(指標)を、商品カテゴリ別・月別(切り口)で」。この“指標”がファクト、“切り口”がディメンションです。

flowchart TB
    DP["dim_product(商品)"] --> F["fact_sales(売上ファクト)"]
    DD["dim_date(日付)"] --> F
    DS["dim_store(店舗)"] --> F
    DC["dim_customer(顧客)"] --> F

ファクトは数値と外部キーだけを細く長く持ち、ディメンションはテキストの属性を持って横に広い。この形が、分析クエリと相性抜群です。

仕組み ── スタースキーマでの集計

erDiagram
    DIM_PRODUCT ||--o{ FACT_SALES : "product_key"
    DIM_DATE    ||--o{ FACT_SALES : "date_key"
    FACT_SALES {
      int sales_id PK
      int product_key FK
      int date_key FK
      int quantity
      int amount
    }
    DIM_PRODUCT {
      int product_key PK
      text name
      text category
    }
    DIM_DATE {
      int date_key PK
      text ymd
      text month
    }
SELECT p.category, d.month,
       SUM(f.quantity) AS qty, SUM(f.amount) AS sales
FROM fact_sales f
JOIN dim_product p ON f.product_key = p.product_key
JOIN dim_date    d ON f.date_key    = d.date_key
GROUP BY p.category, d.month
ORDER BY sales DESC;

実行結果(実機・SQLite):

category | month   | qty | sales
Drink    | 2026-06 |   9 | 2650
Food     | 2026-06 |   6 | 2400

ファクトを中心に、欲しい切り口のディメンションをJOINしてGROUP BYするだけ。切り口を足したいなら別のdimをJOINするだけで拡張できます。これがスタースキーマの“読みやすさ”です。

設計の勘所 ── 粒度・SCD・スノーフレーク

なぜそうするか ── 分析に最適化した非正規化

なぜ リレーショナルモデルと正規化 で学んだ正規化に逆らい、ディメンションをあえて非正規化(カテゴリ名を商品dimに直書き)するのか。分析は読み取りが主で更新が少ないからです。更新時異常のリスクが小さい一方、JOINを減らせばクエリが速く・SQLが単純になる。OLTP(更新系)と違い、OLAP(分析系)では読みやすさ・速さ>更新の厳密さ。この判断軸の全体像が 正規化と非正規化のトレードオフ です。

⚠️ よくある落とし穴

対応ラボ

data-engineering-study/labs/02_data_modeling.pyPYTHONIOENCODING=utf-8 で実行・上記の集計を確認済み)。

関連

第2章 データモデリング 目次