Degenerate Dimension (退化ディメンション) は、対応するディメンションテーブルを持たず、[[ファクトテーブル]]に直接置かれるディメンションである。注文番号や請求書番号のようなトランザクション識別子が代表例だが、注文日時や請求日のような日時列も該当する。
注文番号のような列は、同じトランザクションの行を束ねるグループ化キーとして機能し、業務システムへデータを辿るリンクにもなるため、ファクトテーブルに残す価値がある。[[Ralph Kimball]] は、これを [[ディメンショナルモデリング]] の設計テクニックの 1 つに位置づけている。
> [!info]
> 原典は『[[The Data Warehouse Toolkit]]』(3rd Edition) 3 章 "Retail Sales"。Kimball Group の [Degenerate Dimensions](https://www.kimballgroup.com/data-warehouse-business-intelligence-resources/kimball-techniques/dimensional-modeling-techniques/degenerate-dimension/) テクニックとしても解説されている。
> [!note]
> 「degenerate」は、ディメンションに付随していた記述属性とテーブルが失われ、ファクトテーブルの列 1 つにまで退化した状態を指す。通常のディメンションが独立したテーブルとして実体を持つのに対し、Degenerate Dimension にはその実体テーブルが無い。
## 構造
注文明細を粒度とする `fct_order` を例に取る。記述属性は `dim_date` / `dim_customer` / `dim_product` に抽出済みで、ファクトには注文番号 `order_id`・明細行番号 `order_line_number`・注文日時 `order_date` が残っている。
これら 3 列はいずれも他のテーブルへ join せず、ファクトテーブルの中で完結する Degenerate Dimension である。`order_id` と `order_line_number` は記述属性を持たないトランザクション識別子で、ファクトテーブルの粒度を表している。
一方 `order_date` は記述属性を持つが、クエリパフォーマンスやセマンティックレイヤー上の理由でファクトに残す Degenerate Dimension であり、次節で詳述する。
```mermaid
erDiagram
dim_date ||--|{ fct_order : "date_key"
dim_customer ||--|{ fct_order : "customer_key"
dim_product ||--|{ fct_order : "product_key"
fct_order {
order_key int64 "[SK]"
date_key int64 "[FK]"
customer_key int64 "[FK]"
product_key int64 "[FK]"
order_id string "[DD, GD]"
order_line_number int64 "[DD, GD]"
order_date datetime "[DD]"
quantity int64 "[FA]"
amount int64 "[FA]"
}
```
> [!tip]
> トランザクション識別子や日時列は Degenerate Dimension が適する。
>
> 一方、低カーディナリティのフラグやコードは [[Junk Dimension]] に、構造化されていない長文テキストは [[Text Comment Dimension]] にまとめる方が、ファクトテーブルの肥大化を防げる ([[長文テキスト属性は Text Comment Dimension に切り出す]] で詳述)。
## 現代での再評価
DW/BI を取り巻く環境では、トランザクション識別子だけでなく、注文日時や請求日のような日時列も Degenerate Dimension として残す価値が高い。これは列指向 DWH とセマンティックレイヤーの普及で強まった、比較的新しい判断で、理由は 2 つある。
### 1. 列指向 DWH のパーティション分割
列指向 DWH では、テーブルを日付などで分割してスキャン範囲を絞り、クエリコストと実行時間を抑えられる。[[BigQuery]] がその代表例である。
パーティションキーはテーブルの物理列でなければならない。そのため、日付ディメンション側の `full_date` ではなく、ファクトテーブルに残した `order_date` や `billing_date` をパーティションキーに使用する。
### 2. セマンティックレイヤーの時間軸
メトリクスを時間軸に沿って集計するセマンティックレイヤーは、各ファクトテーブルに時間ディメンションを 1 つ要求する。dbt Semantic Layer や Cube がその代表例である。
ファクトテーブルに残した `order_date` や `billing_date` が、その時間軸としてそのまま機能する。これらはカレンダーの属性 (年月、曜日、祝日フラグなど) を日次粒度で持つ日付ディメンションとは役割が重ならないため共存できる。