[Clickhouse] MergeTreeを設定したら、裏側はどんな動きでしょうか

# 概要
この記事は[ここ](https://segmentfault.com/a/1190000023089140)引用し、知識を整理するために、記載しました。

# なぜMergeTreeはいる？
データをClickHouseに書き込む時、ClickHouseはデータを複数のブロックを分けて、保存しているそうです。ClickHouseは、ブロックのデータを確保し、そのブロックのデータを変更したりはしない。(新しいデータをインサートする時は、ブロックに上書きしたりしないと自分の認識です。)ブロックは多くなると、データは下記のように、不連続となると思います。

![スクリーンショット 2021-03-27 16.50.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1184340/c5499f73-2ad5-5eff-06ca-4ef2fc6c0a88.png)

不連続のデータは検索する時、効率は下がるため、ClickHoseは裏側で、定期的に同じパーティションと設定されているデータをマージするようです。

![スクリーンショット 2021-03-27 16.55.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1184340/d57dcf3f-9387-eb42-a864-6871b0f24bd0.png)

# MergeTreeはどうやってマージするのか

ClickHouseではテーブルを作成する時、よく使っているテーブルエンジンMergeTreeですが、MergeTreeを設定する時、ClickHouseはどうやって、パーティションをマージしているんでしょうか？例えば、下記のSQLを使って、テーブルを作成してみました。

```SQL
CREATE TABLE test 
(
    user_id String,
    date Date, 
    group_id String
) ENGINE = MergeTree()
    ORDER BY (user_id, date,group_id) 
    PRIMARY KEY (user_id, date)
    PARTITION BY toYYYYMM(date)
    SETTINGS index_granularity= 8192 ;
```

上記のSQLを実行し終わると、下記のところにファイルは作成された。

```python
#path database/metadata/test.sql
ATTACH DATABASE _ UUID '0eb2002c-834c-4eb7-ac2f-35160d976765'
ENGINE = Atomic
```

上記の`UUID`を使って、検索してみたら、このUUIDを使って、命名しているディレクトリーはあった。

```python
# database/store/0eb/0eb2002c-834c-4eb7-ac2f-35160d976765
```

上記のディレクトリーの配下には`test.sql`というファイルがあり、それはさっき実行したSQL文でした。

```SQL
-- database/store/0eb/0eb2002c-834c-4eb7-ac2f-35160d976765/test.sql--
ATTACH TABLE _ UUID '48794f04-7524-46f7-a489-66cabed437c1'
(
    `user_id` String,
    `date` Date,
    `group_id` String
)
ENGINE = MergeTree
PARTITION BY toYYYYMM(date)
PRIMARY KEY (user_id, date)
ORDER BY (user_id, date, group_id)
SETTINGS index_granularity = 8192
```

ちょっと、データをインサートしてみます。

```SQL
INSERT INTO test (`user_id`, `date`, `group_id`) values ('1', toDate(now()), '1');
```

上記の`test.sql`にもテーブルの`UUID`は記載していますので、もう一回この`UUID`を使って、検索してみたら、デーブルのパーティションを管理するディレクトリにたどり着けます。

```python
# database/store/487/48794f04-7524-46f7-a489-66cabed437c1/
```

ちょっとこのディレクトの配下みてみると、下記の感じです。

```bash
└── 48794f04-7524-46f7-a489-66cabed437c1    (テーブルのUUID)
    ├── 202103_1_1_0                        (parition名)
    │   ├── checksums.txt
    │   ├── columns.txt                     (カラム定義に関するファイル)
    │   ├── count.txt
    │   ├── data.bin
    │   ├── data.mrk3
    │   ├── default_compression_codec.txt
    │   ├── minmax_date.idx                (paritionキーを設定すると、作成されるファイル)
    │   ├── partition.dat                  (paritionキーを設定すると、作成されるファイル)

    │   └── primary.idx                    (primaryキー情報)
    ├── detached
    └── format_version.txt
```

上記のファイルによって、ClickHouseはテーブルのインデックスなど管理しているようですね。この時、あること気付きました。パーティション名はテーブルを作成した時、設定されている`PARTITION BY toYYYYMM(date)`によって、命名したように見えますね。パーティション名の構成は下記の感じです。

```bash
paritionID_minBlockNum_maxBlockNum_level
```

`paritionID`の作成は2パターンがあるようですが、`PARTITION BY`を設定する場合は、設定されるキーによって作成し、`PARTITION BY`を設定していない場合は`all `という名前を使います。`minBlockNum`、`maxBlockNum`、`maxBlockNum`、`level`について、自分の理解は曖昧ですので、ここでは割愛です。
次はマージの過程をみてみると、下記のイメージです。

![スクリーンショット 2021-03-27 18.50.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1184340/1be4fd21-4701-c69f-f51d-5e173f03aac4.png)

`minBlockNum`、`maxBlockNum`、`level`は上記のイメージで計算しているようです。

# まとめ
一部のことはまだ理解していないんですが、パーティションのマージについて、一応イメージを掴みました。