【snowflake】マイクロパーティションの利点を整理してみた

## はじめに
snowflake初心者がその特徴を理解していくために、投稿します。
今回は、目玉？機能？でもある「マイクロパーティション」について、整理していこうと思います

## 今回の記事で使用するテーブル
以降の説明では、⇩のテーブルを例にパーティションについて整理していきます。

- 購入情報管理テーブル（1.5億レコード）

| order_id | purchase_date | amount | customer_id |
|:-:|:-:|:-:|:-:|
|  1 |  2023-01-30 |  1000 | A001  |
|  2 | 2023-01-31  |  2000 |  A002 |
|  3 | 2023-02-01  |  3000 | A003  |
|  4 |  2023-02-02 |  4000 | A004  |
|  5 | 2023-02-03  | 5000  | A005  |
|  ・・ | ・・  | ・・  | ・・  |
|  150,000,000 | 2024-01-30   | 1000  | A001  |



## RDBMSでもパーティションってなかったっけ？

### 静的パーティションってどんなもの？
この静的パーティションは例えば、先ほどのテーブルを以下のように月毎に分割します。

- パーティション2023-01

| order_id | purchase_date | amount | customer_id |
|:-:|:-:|:-:|:-:|
|  1 |  2023-01-01 |  1000 | A001  |
|  2 | 2023-01-10  |  2000 |  A002 |
|  3 | 2023-01-20  |  3000 | A003  |
|  4 |  2023-01-31 |  4000 | A004  |
|  ・・ | ・・  | ・・  | ・・  |

- パーティション2023-02

| order_id | purchase_date | amount | customer_id |
|:-:|:-:|:-:|:-:|
|  5,000,001 |  2023-02-01 |  1000 | A001  |
|  5,000,002 | 2023-02-10  |  2000 |  A002 |
|  5,000,003 | 2023-02-20  |  3000 | A003  |
|  5,000,004 |  2023-02-31 |  4000 | A004  |
|  ・・ | ・・  | ・・  | ・・  |


このパーティションを行うことで、以下クエリを発行すると・・・

![パーティション.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3760174/9d50d0e2-1acd-4d55-a06d-e39b592431d9.jpeg)

パーティション2023-01のみを参照するので、検索効率が上がります。

### 静的パーティションの抱える問題は？？
じゃあ、マイクロパーティションなんか実装せず、静的パーティションでいいじゃないか。と思いますが、欠点はあります

- ç
「静的」と言われるだけあり、パーティション作成は以下のように事前に定義する必要があります。

    -  1. 静的パーティションの作成
        ````
            CREATE TABLE sales (
                id SERIAL PRIMARY KEY,
                purchase_date DATE NOT NULL,
                amount DECIMAL(10,2) NOT NULL
            ) PARTITION BY RANGE (purchase_date);
        ````
        <br>
    -  2. 年月ごとのパーティションの作成
         ````
            CREATE TABLE sales_202301 PARTITION OF sales
                FOR VALUES FROM ('2023-01-01') TO ('2023-02-01');
            
            CREATE TABLE sales_202302 PARTITION OF sales
                FOR VALUES FROM ('2023-02-01') TO ('2023-03-01');
        ````

    そのため、メンテナンスとして、パーティションを随時追加していく（2024-01月分を作らなきゃ）作業が発生してしまいます。

<br>

- データの偏りが発生する
年月でパーティションをしていますが、購入件数は月毎に偏りが出る可能性が考えられます。
    - パーティション2023-01：500万レコード
    - パーティション2023-02：1億レコード

<br>

- 境界のデータへの効率が悪い
例えば、2023-01-30〜2023-02-01のデータを読み込む場合、日付としては連続しているが、パーティションが別なので、1億5百万レコードをすべて読み込む必要があり、効率が悪い。

    ![パーティション.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3760174/50f24806-f287-48f1-8550-b7047f60151a.jpeg)


## snowflakeのマイクロパーティションってどんな仕組みなんだろう？

- マイクロパーティションの流れ
    - 元のテーブルに対して、列ごとにパーティション分割されます
    - このパーティションは事前定義不要で、snowflakeが自動で行います
![パーティション.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3760174/00580010-7f54-4dc7-a80f-7711f08ce199.jpeg)

<br>

- 実際にクエリが発生すると？？
    - クエリ条件が2023-01-30~02-01の期間を抽出する場合
    - メタデータを参照し、不要なパーティションをスキャン対象から除外する
    ![パーティション.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3760174/d145f240-0e43-4c6c-b49f-06377d2f96e1.jpeg)


## マイクロパーティションは静的パーティションを凌駕する？
では、前述した静的パーティションの問題をマイクロパーティションはどう解決するのでしょうか？

- 手動メンテナンスが必要
- データの偏りが発生する
この課題については、snowflake側が自動でおおよそ均一のパーティションに分割してくれるため、⇩のような偏りは防げるはずです。
     - パーティション2023-01：500万レコード
    - パーティション2023-02：1億レコード

- 境界のデータへの効率が悪い
先ほどの通り、snowflake側が自動でおおよそ均一のパーティションに分割します。
なので、境界のデータ（月をまたぐ1/30~2/1のクエリ）の読み取り効率は
    - 静的パーティションでは1億500万レコードを読み取らなければいけない
    - マイクロパーティションでは1千万レコードの読み取りで済む
![パーティション.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3760174/00c1e291-31bd-462a-bac1-3e87c6a86f0b.jpeg)

ということになり。マイクロパーティションの方が効率的と言えます。


## まとめ
まだまだ、snowflakeは知らないことだらけですが、こうして少しずつ詳しくなっていこうと思います！（誤りがあればぜひ教えていただきたいです）