ウェアハウスキー
スタースキーマでは、各ディメンションテーブルにサロゲートキーが付与される。サロゲートキーとは、データウェアハウス専用に作成された一意の識別子であり、本質的な意味を持たない「シーケンス番号」または「ハッシュ値」で構成される。
このサロゲートキーは、「ウェアハウスキー」とも呼ばれ、ディメンションテーブルのプライマリーキーとして機能する。ウェアハウスキーの導入により、データの一意性が保証され、ディメンションテーブルの関連付けがスムーズになる。また、元のシステムのキー(ナチュラルキー)に依存しないため、データの変更に柔軟に対応できるというメリットもある。
当サイトのスタースキーマの記事では、接尾辞 _key
によってウェアハウスキーを簡単に識別できるようにする。また、スタースキーマの ER 図ではウェアハウスキーを SK
、ナチュラルキーを NK
と表記する。
シーケンス番号 vs ハッシュ値
ウェアハウスキーは、シーケンス番号またはハッシュ値で生成される。筆者は、以下の点を考慮してウェアハウスキーにシーケンス番号ではなくハッシュ値を用いるべきだと考えている。
- 変換プロセスがシンプルになる
- クエリパフォーマンスが良くなる
1. データ変換プロセス
ハッシュ値で作成するウェアハウスキーとシーケンス番号で作成するときウェアハウスキーを比べると、前者の方が変換プロセスがシンプルである。
シーケンス番号の場合
シーケンス番号を使ってウェアハウスキーを作成する場合、アウトリガーなどの依存関係があるテーブルの変換プロセスが複雑になる可能性がある。
例えば、日付情報を管理する「日付ディメンション」と、顧客情報を管理する「顧客ディメンション」があるとする。顧客ディメンションには、誕生日や初回購入日などのユーザーの行動属性が含まれる可能性があり、これらは日付ディメンションとの外部キーを持っている。
この関係から見て分かるように、日付ディメンションと顧客ディメンションには親子関係が存在する。この場合、顧客ディメンションのデータを読み込むためには、先に日付ディメンションのデータを読み込み、ウェアハウスキーを取得する必要がある。この依存関係により、データ読み込みの順序が制約され、プロセスが複雑になる可能性がある。
| date_key | date | ... |
| -------- | ---------- | --- |
| 1 | 1900-01-01 | ... |
| 2 | 1900-01-02 | ... |
| 3 | 1900-01-03 | ... |
| ... | ... | ... |
| user_key | user_id | ... | birth_date | birth_date_key |
| -------- | ------- | --- | ---------- | -------------- |
| 1 | u1 | ... | 2000-01-01 | 36525 |
| 2 | u2 | ... | 1992-01-01 | 33604 |
| 3 | u3 | ... | 1900-01-03 | 3 |
| ... | ... | ... | ... | ... |
ハッシュ値の場合
ハッシュ値を使ってウェアハウスキーを作成する場合、ナチュラルキーに対してハッシュ化を行うので、親テーブルと子テーブルの読み込み処理を分離し、依存関係を解消することができる。これにより、データ読み込みのパフォーマンスが向上し、プロセスがシンプルになる。
| date_key | date | ... |
| -------------------------------- | ---------- | --- |
| 57bf835442e2cf6f551f6c52639afc4c | 1900-01-01 | ... |
| 0e2738c72d39084215b2d5fc0bc3ec4c | 1900-01-02 | ... |
| dec2630316eb8450b33c25482b1957d7 | 1900-01-03 | ... |
| ... | ... | ... |
| user_key | user_id | ... | birth_date | birth_date_key |
| -------------------------------- | ------- | --- | ---------- | -------------------------------- |
| e4774cdda0793f86414e8b9140bb6db4 | u1 | ... | 2000-01-01 | dab573b0f8a422a6f9e8033277ce1751 |
| 270c1b084f3f146eb5787075158d9c53 | u2 | ... | 1992-01-01 | 56bfafe1a37d7da1e8564f67c517a15c |
| 532a7b8e0328a8d05a8e6258b28b9a36 | u3 | ... | 1900-01-03 | dec2630316eb8450b33c25482b1957d7 |
| ... | ... | ... | ... | ... |
2. クエリパフォーマンス
ハッシュ値を使用した結合がシーケンス番号を使用した結合よりも高速になりやすい主な理由は以下の 3 点である。
- データサイズの効率性:
- ハッシュ値は固定長なので、メモリとキャッシュの効率が良い。
- シーケンス番号は可変長なので、データ量が増えるとサイズが大きくなり、効率が悪くなる。
- インデックスの効率性:
- ハッシュ値は固定長なので、インデックスの構築とルックアップが高速。
- シーケンス番号は可変長なので、インデックスのサイズが大きくなり、ルックアップの効率が低下。
- CPU 処理の効率性:
- ハッシュ値の比較は、CPU の命令レベルで最適化されており、高速。
- シーケンス番号の比較は、データサイズが大きくなると CPU の処理時間が長くなる。
つまり、ハッシュ値は固定長であるため、メモリ、キャッシュ、インデックス、CPU 処理の効率が良く、結合操作が高速になる。一方、シーケンス番号は可変長であるため、データ量が増えると効率が悪くなり、結合操作のパフォーマンスが低下する可能性がある。