ケーススタディ

ケーススタディ:データモデリングと設計

実務シナリオ + 設計判断の根拠 — Specialist試験対策


Case 1: EC企業の注文データモデル設計

背景

日本の中規模ECプラットフォーム(月間注文数100万件)。初期モデルが粗く、以下の問題が発生:

問題のある初期設計

-- アンチパターン:EAV(Entity-Attribute-Value)
CREATE TABLE product_attributes (
    product_id    INT,
    attr_name     VARCHAR(100),  -- 'size', 'color', 'weight' etc.
    attr_value    VARCHAR(500)
);

EAVの問題点(試験で問われる):

改善された論理モデル設計

[OrderHeader]
- order_id (PK, Surrogate)
- customer_id (FK)
- order_datetime
- order_status_cd (FK → OrderStatus)
- channel_cd (FK → SalesChannel)

[OrderLine]
- order_line_id (PK, Surrogate)
- order_id (FK)
- product_variant_id (FK)
- quantity
- unit_price_at_order    ← 注文時点の価格を記録(重要)
- discount_amount
- list_price_at_order

[ProductVariant]
- variant_id (PK, Surrogate)
- product_id (FK)
- size_cd
- color_cd
- sku

[Product]
- product_id (PK, Surrogate)
- product_name
- category_id (FK)
- base_price

設計判断の解説

なぜサロゲートキーか?

価格を注文時点で記録する理由:

物理モデルへの変換(パフォーマンス考慮)

-- 論理モデルの 3NF を物理で部分的に非正規化
-- 注文検索のホットパス最適化
CREATE TABLE order_line (
    order_line_id        BIGINT PRIMARY KEY,
    order_id             BIGINT NOT NULL,
    product_variant_id   INT NOT NULL,
    quantity             INT NOT NULL,
    unit_price_at_order  DECIMAL(10,2) NOT NULL,
    -- 非正規化(JOINコスト削減)
    product_name_snapshot VARCHAR(200),  -- 注文時の商品名
    variant_desc_snapshot VARCHAR(100),  -- 注文時のバリアント説明
    INDEX idx_order_id (order_id),
    INDEX idx_created (created_at)
) PARTITION BY RANGE (YEAR(created_at));  -- 年次パーティション

設計原則: 論理モデルは3NF(整合性優先)、物理モデルは意図的な非正規化(パフォーマンス優先)


Case 2: SCD Type 2 の実装とピットフォール

背景

データウェアハウスの顧客ディメンション設計。顧客の住所が変わった場合に「以前の住所を使った注文」と「新しい住所を使った注文」を正確に分析したい。

SCD Type 2 の完全な設計

CREATE TABLE dim_customer (
    customer_key        INT PRIMARY KEY,        -- Surrogate Key(DWH用)
    customer_natural_id VARCHAR(20) NOT NULL,   -- ナチュラルキー(元システムのID)
    customer_name       VARCHAR(100),
    address_line1       VARCHAR(200),
    prefecture_cd       CHAR(2),
    
    -- SCD Type 2 制御カラム
    effective_from_dt   DATE NOT NULL,          -- この行が有効になった日
    effective_to_dt     DATE,                   -- この行が無効になった日(NULLは現在有効)
    is_current_flag     CHAR(1) DEFAULT 'Y',    -- 現在有効行フラグ
    dw_created_dt       DATETIME,               -- DWHへの挿入日時
    source_system_cd    VARCHAR(10)             -- ソースシステム識別子
);

実装のポイントと落とし穴

正しいクエリパターン:

-- 現在の顧客情報
SELECT * FROM dim_customer WHERE is_current_flag = 'Y';

-- 特定日時点の顧客情報(Temporal Query)
SELECT * FROM dim_customer
WHERE customer_natural_id = 'C001'
  AND effective_from_dt <= '2023-06-15'
  AND (effective_to_dt > '2023-06-15' OR effective_to_dt IS NULL);

よくある実装ミス:

  1. effective_to_dt に NULL と '9999-12-31' が混在 → クエリが複雑化
  2. 複数レコードで is_current_flag = 'Y' が付く(ETL処理の冪等性が保たれていない)
  3. Natural Key のインデックスがない → 特定顧客の全履歴検索が遅い

SCD タイプの選択基準(試験頻出)

SCD Type 使いどき 実務例
Type 1 誤り訂正・過去は気にしない 電話番号の誤入力修正
Type 2 完全な変更履歴が必要 顧客住所変更(地域別分析に影響)
Type 3 変更前/変更後の比較のみ 部門変更(現在と1つ前だけ)
Type 4 ヒストリーを別テーブルに分離 急速に変わる属性(価格等)
Type 6 Type 1 + 2 + 3 の組み合わせ 複雑なケース(Kimball推奨)

試験注意: Type 4, 5, 6 はFundamentals試験には出ないが、DW&BI Specialist試験では出題される。


Case 3: データモデルのアンチパターン診断

アンチパターン1: God Table(神テーブル)

症状:

-- 500カラム以上、あらゆるデータが1テーブルに
CREATE TABLE customer_all (
    id INT PRIMARY KEY,
    name VARCHAR(100),
    address VARCHAR(500),
    credit_score INT,
    -- ... 497カラム続く
    order_count INT,      -- 集計値が入ってる!
    last_order_date DATE  -- 集計値が入ってる!
);

問題点:

正しい対処:

アンチパターン2: 意味のある複合主キー

-- 問題:2つのビジネスキーの組み合わせをPKにする
CREATE TABLE order_item (
    order_id     INT,
    product_code VARCHAR(20),
    -- ... 
    PRIMARY KEY (order_id, product_code)
);

問題点:

正しい対処: サロゲートキーを追加してPKとし、業務キーはUNIQUE制約で保証

アンチパターン3: 汎用ステータステーブル

-- アンチパターン
CREATE TABLE statuses (
    entity_type VARCHAR(50),  -- 'order', 'customer', 'product'
    status_code VARCHAR(20),
    status_name VARCHAR(100)
);

問題点:

正しい対処: エンティティごとに独立したステータステーブル(order_status, customer_status


Case 4: データモデルレビューの実施

レビューの4つの観点(Specialist試験で出題)

1. ビジネス要件との整合性(Business Alignment)

2. データ整合性(Data Integrity)

3. 設計の一貫性(Design Consistency)

4. パフォーマンス考慮(Performance Considerations)

レビューチェックリスト(実務で使える)

□ エンティティ定義がBusiness Glossaryと一致している
□ すべての必須属性に NOT NULL が設定されている
□ 外部キーにはインデックスが存在する
□ 命名規則ドキュメントに準拠している
□ SCD タイプの選択理由が文書化されている
□ ビジネスステークホルダーのレビューと承認が完了している
□ バージョン管理システムにモデルが保存されている

Specialist試験の頻出シナリオ問題

問題1

小売業のDWHチームが顧客セグメント変更(Gold→Silver等)を追跡する必要がある。変更前後の双方のセグメントで売上を集計したい。どのSCDタイプが最適か?

解答: SCD Type 2(新行追加で履歴を保持)。Type 3では直前の変更しか追えない。Type 1では履歴が消える。

問題2

データモデラーが「製品バリアント(サイズ×カラー)」の属性設計で悩んでいる。バリアントごとに属性数が異なる(靴にはサイズがあるが色はない場合も)。EAVパターンを提案されたが、データモデラーとして何を推奨するか?

解答: EAVは避ける。代わりに、

問題3

Reverse Engineeringの主な目的は?

解答: 既存のDBから論理・概念データモデルを再構築し、文書化すること。レガシーシステムの理解、移行計画の策定、コンプライアンス要件への対応に使用される。