【テクニカル・上級編】 宣言的パーティショニング – PostgreSQL

宣言的パーティショニング:PostgreSQLで「巨大なテーブル」を飼い慣らすための作法

PostgreSQLの運用歴が長くなると、必ず直面する壁がある。数億行、あるいは数十億行に達した巨大テーブルだ。かつては `inherit` を使った力技の継承テーブル設計で凌いできたものだが、PostgreSQL 10以降、ようやく我々が待ち望んでいた「宣言的パーティショニング」が標準機能として実装された。

今回は、この「宣言的パーティショニング」の裏側と、大規模DBのパフォーマンスを維持するためのインデックス戦略について、教科書には載っていない(載っていても読み飛ばされがちな)現場の知見を共有したいと思う。

—

なぜ今、宣言的パーティショニングなのか

昔ながらの継承パーティショニングは、制約チェックやトリガーによるルーティングが必要で、正直なところ「運用者の気合」に依存する部分が大きかった。一方、`CREATE TABLE … PARTITION BY` を用いた宣言的パーティショニングは、クエリプランナがパーティションの構造を「最初から知っている」点が決定的に違う。

クエリプランナは `WHERE` 句の条件を見て、対象外のパーティションを即座に無視する。これが有名なパーティションプルーニング(Partition Pruning)だ。これにより、数TBのデータがあっても、数MBの小さなインデックスだけを走査してクエリが完了する。この爽快感は、一度味わうと手放せない。

3つの戦略:RANGE, LIST, HASH

設計の基本だが、ここにはエンジニアの哲学が出る。

  • RANGEパーティショニング: 時系列データには最適だ。「先月のデータはアーカイブへ、今月のデータは高速ストレージへ」といったライフサイクル管理が容易になる。
  • LISTパーティショニング: 地域コードやステータスなど、カテゴリが明確な場合に適している。ただ、キーの偏りには注意が必要だ。特定のパーティションだけが肥大化すると、結局ボトルネックになる。
  • HASHパーティショニング: 負荷分散の最終兵器だ。キーのカーディナリティが高い場合、データが均等に分散されるため、特定のパーティションにI/Oが集中するのを防げる。ただし、範囲指定(`range query`)にはめっぽう弱いので注意が必要だ。

—

パフォーマンストラブルの「深淵」を覗く

さて、ここからが本題だ。宣言的パーティショニングを使えば万事解決かというと、そうではない。現場でよく見る「ハマりポイント」をいくつか挙げておこう。

1. プルーニングが効かない「インデックスの罠」

クエリがインデックスを貼っているはずなのに、なぜか全パーティションをスキャン(Full Table Scan)している……そんな経験はないだろうか。
原因の多くは「型の一致」だ。例えば、パーティションキーが `BIGINT` なのに、クエリの `WHERE` 句で `VARCHAR` の値を渡していれば、暗黙の型変換が走り、プランナは「安全策」をとって全パーティションを覗きに行くことになる。`EXPLAIN` を叩いて `Subplans Removed` の項目を確認するのは、エンジニアの嗜みだ。

2. パーティションの細分化という落とし穴

「パーティションを細かく分ければ分けるほど速い」と信じているエンジニアがいるが、これは大きな誤解だ。
パーティションが増えすぎると、プランナの解析コストが跳ね上がる。数千個のパーティションを持つテーブルに対して `INSERT` や `SELECT` を投げれば、それだけでCPUを食いつぶすことになる。適切な粒度は、データ量だけでなく「一度のクエリでアクセスする範囲」を基準に決めるべきだ。

3. グローバルインデックスの欠如

PostgreSQLのパーティショニングにおいて、現状「ユニーク制約」はパーティションキーを含まなければならない。これは分散DBとしての制約だが、実務上はかなり制約が強い。もし「パーティションを跨いで一意性を保証したい」という要件があるなら、それはアプリケーション層での工夫か、あるいは `pg_partman` のような拡張機能を使いこなす、あるいはそもそもアーキテクチャを見直す必要がある。

—

エンジニアとしての「感触」

大規模なデータセットを扱うとき、私は常に「データがどこにあるか」を直感的にイメージできるように設計を組む。

`CREATE TABLE … PARTITION BY` は、単なるDDLではない。それはデータに対する「地図」を作ることだ。適切に設計された地図は、クエリを目的地まで最短ルートで導いてくれるが、設計を怠れば、プランナという優秀なガイドは迷子になり、システム全体が悲鳴を上げる。

最後にアドバイスを一つ。「とりあえず作ってから考える」のはやめよう。
`EXPLAIN ANALYZE` を徹底的に読み込み、パーティションプルーニングが機能しているか、インデックスが効果的に効いているか。その「感触」を研ぎ澄ませることが、DBエンジニアとして一段上のステージに上がるための近道だと、私は信じている。

さて、今日はここまで。また、深い技術の話でお会いしよう。

コメント

タイトルとURLをコピーしました