DBのパーティショニングを理解する

# はじめに

データベースのパーティショニングを理解するためのメモです。

# 目次
- [パーティショニングとは](https://qiita.com/esnir74/items/8ad4e6d431ce8aaa6638#%E3%83%91%E3%83%BC%E3%83%86%E3%82%A3%E3%82%B7%E3%83%A7%E3%83%8B%E3%83%B3%E3%82%B0%E3%81%A8%E3%81%AF)
- [メリット](https://qiita.com/esnir74/items/8ad4e6d431ce8aaa6638#%E3%83%A1%E3%83%AA%E3%83%83%E3%83%88)
- [デメリット](https://qiita.com/esnir74/items/8ad4e6d431ce8aaa6638#%E3%83%87%E3%83%A1%E3%83%AA%E3%83%83%E3%83%88)
- [パーティションの種類](https://qiita.com/esnir74/items/8ad4e6d431ce8aaa6638#%E3%83%91%E3%83%BC%E3%83%86%E3%82%A3%E3%82%B7%E3%83%A7%E3%83%B3%E3%81%AE%E7%A8%AE%E9%A1%9E)
- [レプリケーションとの違い](https://qiita.com/esnir74/items/8ad4e6d431ce8aaa6638#%E3%83%AC%E3%83%97%E3%83%AA%E3%82%B1%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E3%81%A8%E3%81%AE%E9%81%95%E3%81%84)
- [シャーディングとの違い](https://qiita.com/esnir74/items/8ad4e6d431ce8aaa6638#%E3%82%B7%E3%83%A3%E3%83%BC%E3%83%87%E3%82%A3%E3%83%B3%E3%82%B0%E3%81%A8%E3%81%AE%E9%81%95%E3%81%84)
- [参考](https://qiita.com/esnir74/items/8ad4e6d431ce8aaa6638#%E5%8F%82%E8%80%83)

# パーティショニングとは
論理的には１つのテーブルを、物理的により小さな部品に分割すること。
アプリケーションからは１つのテーブルとして扱うことができる。
単一のデータベース内でのお話。

※レプリケーションやシャーディングとの違いは後述

# メリット
大きく分けて
- パフォーマンスの向上
- メンテナンス性の向上

という２つのメリットがある。

### パフォーマンスの向上

- 検索範囲を絞り込むことができる
    - 適切な分割によってアクセスする対象を特定のパーティションのみに特定することができる 
- キャッシュを有効活用できる
    - 頻繁にアクセスされるデータとそうでないデータを分けることができるので、頻繁にアクセスするデータを格納しているパーティションを優先してキャッシュに保存できる
- 操作の分散
    - 別々の物理ディスクに配置することによって、それぞれに対して並行で読み書きが行われる。ディスクI/Oが分散して処理性能が向上する  
- アプリケーション側でパーティションの分離を意識する必要がない
    - 以上のメリットは、単にテーブルを分割すれば享受できるメリットであったが、レプリケーションは、アプリケーション側でパーティションの分離を意識する必要がないというメリットがある

パフォーマンス向上のメリットは通常、パーティショニングをしなければテーブルが非常に大きくなる場合にのみ得ることができる。テーブルのサイズがデータベースサーバの物理メモリより大きい場合など。

### メンテナンス性の向上
- テーブル単位での操作が可能
    - テーブル単位で削除・作成などの操作を行えるので、時系列データに対して、月ごとにパーティションを分割する場合などに、テーブルに対する操作が速くなる
    - 具体的には、個別の行データに対する`DELETE`ではなく、`TRUNCATE`によるデータの削除が行えるので処理速度が高速化される
    - VACUUMなどの後処理の負荷も軽減できる
- 運用コスト削減
    - 頻繁にアクセスされるデータとそうでないデータを分けることができるので、後者を安価で低速なストレージメディアに移行できる
# デメリット
デメリットも存在する。それぞれのRDBMSによってサポートしているものがまちまちなので、実装の際は個別のドキュメントを参照されたい。
- INSERT性能の低下
    - 親テーブルへのINSERTをトリガーとして、子テーブルへの振り分け処理がなされるので、INSERTの性能は落ちる
- パーティションをまたいだユニーク制約をサポートしていないものがある
- IMMUTABLE 属性以外の関数を使用する場合、早期絞り込みが行われないこともある
    - PostgreSQLではサポートしていない
    - 現在時刻の取得はアプリ側で行うことが求められる
- パーティション間のクエリが増えると処理が複雑になる

# パーティションの種類
- レンジパーティション
    - 値の範囲・期間ごとに分割する
    - 最近のデータのアクセスが多い場合などに有効
    - 例：５月度、６月度、７月度
- リストパーティション
    - あらかじめ決められた値で分割する
    - パーティションごとに集計が必要な場合にアクセスの範囲を絞れるので有効
    - 例：都道府県、部署など
- ハッシュパーティション
    - パーティションキーとする値をハッシュ化したあとの値を、分割数で割った剰余ごとに分割
    - データを分割したディスクごとに均等に配置したい場合に有効
    - insertの頻度が高い場合、テーブルの末尾にアクセスが集中して、ロックがかかりやすくなっている
        - ハッシュ分割を行うことによって、実質的に複数のデータ末尾を作ることができるので、アクセスを分散させることができる


# レプリケーションとの違い
レプリケーションはデータの複製。
負荷分散や可用性向上のために、同じデータのレプリカを作成する。
パーティションはそもそも書き込むテーブルを分ける。

一般にレプリケーションとパーティショニングは組み合わせて使用される。
各パーティションのコピーが複数のノードに保存される。
# シャーディングとの違い
シャーディングはDBの水平スケーリングのための手段。
サーバーを分けて負荷分散や可用性の向上を図る。

パーティショニングは単一データベース内の物理的な分割。上記の通り、パフォーマンス向上などの理由で使用される

# 参考
https://www.baeldung.com/cs/database-sharding-vs-partitioning

https://dev.mysql.com/doc/refman/8.0/ja/partitioning-overview.html

https://www.fujitsu.com/jp/products/software/resources/feature-stories/postgres/article-index/partitioning-overview/

https://lets.postgresql.jp/documents/technical/partitioning/1