Data Modeling with Snowflakeを読んでみた

この記事は [Snowflake Advent Calendar 2023](https://qiita.com/advent-calendar/2023/snowflake) Series 1 の13日目です。
## はじめに
私は、データ基盤の設計を勉強中です。この記事では、「[Data Modeling with Snowflake](https://www.amazon.co.jp/Data-Modeling-Snowflake-accelerating-development-ebook/dp/B0BXSMGJDX/)」という書籍を紹介します。

## 本書の概要

### 著者

著者のSerge Gershkovich氏は、モデリングツールSqlDBMにて、データアーキテクトとしての経験を持ち、Snowflake Data Superheroとしても活躍しています。書籍発売後に追加されたSnowflakeの新機能を踏まえて、本書の更新も検討されているとのことです。

### 構成
本書は説明が明瞭で、ロンドンの地下鉄路線図やスーパーヒーロー(snowflakeだけに)など、親近感のある例が使われており、読みやすいです。
構成としては、一般的なデータモデリング、Snowflake、DWHでいうところのデータ変換をカバーしています。主なトピックは以下の通りです。（実際の章の順序とは異なります）

- データモデリング
    - モデリングとは（1, 2章）
    - 概念・論理モデリング（7, 8章）
    - 正規化（9章）
    - モデリング図の表記法（6章）
    - 物理モデリング（11章）
- Snowflake の概要
    - アーキテクチャ、オブジェクト（3～5章）
    - 命名と環境構成（10章）
- データ基盤におけるモデリング（Transformational modeling：ELTのT）
    - 性能改善（12章）
    - ディメンショナルモデル（13, 14章）
    - 階層データ（16章）
    - 半構造化データ（15章）
    - Data Vault、データメッシュ（17章）

## 内容紹介

データ基盤におけるモデリングのパートから、一部の内容を紹介します。

### ソースシステムの物理削除を補完 ：stream

ディメンショナルモデルにおけるファクトの履歴データを想定します。単純合計で正しい値を得るためには、削除・更新時は一旦マイナス値で打ち消した後、新たな値を登録する（赤黒処理）ことが望ましいです。しかし、ソースシステムで物理更新・物理削除してしまうケースがあります。

本書では、このようなケースに対して、Snowflake の stream 機能が有効であると説明しています。

stream とは、テーブルの変更履歴を記録する機能です。ソースシステムで物理削除されたレコードの変更履歴を stream から読み込んでファクトテーブルに反映することで、赤黒更新を実現します。
    
![streamによる物理削除の補完例 figure 14.9](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/164170/07761f66-3811-0b85-57be-5262608707a1.png)

### ディメンションSCD type2の実装 ：stream

ディメンションSCD type2 を、以下の 2ステップで実現すると想定します。
1. 最新のレコード反映（SCD type 1 と同じ）
1. 更新したレコードの変更前の状態を登録

本書では、この 2 つ目のステップにも stream を利用すると、dbt のスナップショットと比較して 40% 高速に処理できると説明しています。

1000行程度ではdbtと同等です。対象件数が150万行に増えると、dbtが21秒に対して、streamを利用した方法では13秒で完了しています。

![dbtのスナップショットとの処理時間比較](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/164170/9d515969-868a-745e-51e1-23619be704d7.png)
        [本書githubリポジトリch13より](https://github.com/PacktPublishing/Data-Modeling-with-Snowflake)

### 階層構造ディメンションの展開：CONNECT BY & SYS_CONNECT_BY_PATH

ディメンション属性に親会社・子会社等の階層構造を持つ場合を想定します。階層を表現するにはデータを再帰的にたどる必要があり、クエリが複雑になります。

本書では、このようなケースに対して、CONNECT BY 句や SYS_CONNECT_BY_PATH 関数を活用すると、各レコードに階層構造を展開できると説明しています。

CONNECT BY句により、再帰的なクエリをシンプルに記述できます。また、SYS_CONNECT_BY_PATH関数は、ルートからのパスを文字列で取得できます。

これにより、階層構造の複雑さをファクトから分離できます。
![階層ディメンションの展開例 Figure 16.8](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/164170/d25a8c26-dda8-2a5e-bcd8-f221bb718851.png)


        
## 最後に

本書は、データモデリングの基礎を学べるだけでなく、具体的・実践的な内容が豊富に含まれています。データ基盤の構築や運用に携わるエンジニアの皆様にぜひお勧めします。

それでは良いお年をお迎えください。

## 参考リンク
- 著者インタビュー：[Behind The Cape: Data Modeling with Snowflake](https://www.youtube.com/watch?v=LAJf9fFrV3k)
- [Data Modeling with Snowflake : table of contents](https://www.oreilly.com/library/view/data-modeling-with/9781837634453/)
- 公式docs：[rely : Snowflakeが冗長な結合を削除する方法を理解する](https://docs.snowflake.com/ja/user-guide/join-elimination)
- [zenn：RELY制約の検証](https://zenn.dev/daisuke_harato/articles/86a6deedff2f36)      
- [zenn : スロー・チェンジ・ディメンション(Slowly Changing Dimensions)](https://zenn.dev/pei0804/articles/slowly-changing-dimensions)
- [Snowflakeで階層問合せを試してみた｜分析屋](https://note.com/bunsekiya_tech/n/nf529f8157f18)
- 公式docs：[CONNECT BY](https://docs.snowflake.com/ja/sql-reference/constructs/connect-by)