「巨大なテーブル、どう分割する?」——PostgreSQL継承とFDWで実現する、無理のない分散データモデル
やあ。データベースの運用、順調かな?
最近、後輩から「テーブルの肥大化が止まらなくて、クエリがどんどん重くなってるんです……パーティショニングすべきでしょうか?」という相談を受けたんだ。もちろん、現代のPostgreSQLなら`PARTITION BY`を使うのが正攻法だ。でも、物理的にサーバーを分けなきゃいけないような「究極の分散」が必要な場面に直面したとき、君ならどうする?
今回は、ちょっと渋いけれど、ハマると非常に強力な「テーブル継承(Inheritance)」と「FDW(Foreign Data Wrapper)」の組み合わせについて話そうと思う。
—
なぜ「継承」と「FDW」を組み合わせるのか?
PostgreSQLの継承機能は、実は「パーティショニング」が標準機能として実装されるずっと前から存在していた、いわば古参の仕組みだ。
普通、パーティショニングは同一インスタンス内でテーブルを分割するものだけど、FDWを組み合わせることで、「親テーブルはローカルにあるけど、子テーブルの実体は別のサーバーにある」という構成が作れる。これを使えば、古いログデータを安価な別のサーバーへオフロードしたり、リージョンごとにデータを散らしたりすることが可能になるんだ。
実践:こうやって組み立てる
まずは、親テーブル(論理的な窓口)と、リモートサーバーにある子テーブルを定義してみよう。
1. FDWの設定(準備運動)
まずはリモートサーバーへ接続する口を作る。
— postgres_fdw拡張を有効化
CREATE EXTENSION postgres_fdw;
— リモートサーバーの定義
CREATE SERVER remote_server
FOREIGN DATA WRAPPER postgres_fdw
OPTIONS (host ‘192.168.1.50’, dbname ‘archive_db’);
— ユーザーマッピング
CREATE USER MAPPING FOR current_user
SERVER remote_server OPTIONS (user ‘remote_user’, password ‘secret’);
2. 親テーブルと子テーブルの定義
ここで重要なのが「継承」だ。
— 親テーブル(ここをクエリする)
CREATE TABLE sales_data (
id SERIAL,
sale_date DATE NOT NULL,
amount NUMERIC
);
— リモートにある子テーブル(外部テーブルとして作成)
CREATE FOREIGN TABLE sales_data_2023 (
CHECK (sale_date >= ‘2023-01-01’ AND sale_date < '2024-01-01')
) INHERITS (sales_data)
SERVER remote_server OPTIONS (table_name 'sales_2023');
---
ここが肝!「制約排除(Constraint Exclusion)」の魔法
さて、ここからがエンジニアの腕の見せ所だ。
「継承したテーブルが100個あったら、クエリのたびに全部見に行くのか?」と心配になるかもしれないけど、そこで登場するのが「制約排除(Constraint Exclusion)」だ。
PostgreSQLは、クエリのWHERE句と、各テーブルに設定されたCHECK制約を照らし合わせる。もし「2023年のデータが欲しい」というクエリを投げれば、DBエンジンは「あ、`sales_data_2023`以外は見る必要ないな」と判断して、他の外部テーブルへのネットワーク通信をバッサリカットしてくれるんだ。
注意してほしいこと
この挙動を確実に発揮させるには、`postgresql.conf`で以下を確認しておいてほしい。
constraint_exclusion = partition # ‘on’ でもいいが ‘partition’ が推奨
もしこれが `off` だと、全サーバーへネットワークを張りにいってしまい、せっかくの分散構成が「劇遅」システムに早変わりだ。ここ、テストに出るレベルで重要だよ。
—
先輩からのアドバイス:この構成の「罠」
この手法、一見便利そうだけど、実務では注意すべき点がいくつかある。
1. インデックスの継承はされない
親テーブルに対してインデックスを貼っても、外部テーブル(子)には自動で反映されない。リモート側でもちゃんとインデックスを貼る必要がある。これを忘れると、リモート側でフルスキャンが発生して即死するぞ。
2. 統計情報の同期
リモートのデータ量が変わっても、ローカルの親テーブルはそれを知らない。「`ANALYZE`をどうやって自動化するか」が運用設計のキモになる。`postgres_fdw`には`use_remote_estimate`というオプションがあるから、これを有効にしてリモート側の統計を使うのが基本だ。
3. 最近のトレンドと比較する
正直に言おう。PostgreSQL 10以降の「宣言的パーティショニング」は、FDWと組み合わせた場合でもかなり洗練されている。特別な理由がなければ、古い継承機能よりも宣言的パーティショニングの利用を優先したほうが、運用負荷は圧倒的に低い。
—
まとめ
「テーブル継承+FDW」は、古き良きPostgreSQLの力技だ。
複雑なサーバー構成を組まざるを得ないときや、既存のレガシーなデータアーカイブを統合したいとき、この知識は君の武器になる。
でも、「複雑さは悪」だ。まずは宣言的パーティショニングで解決できないか検討し、どうしても物理的な分離が必要なときの「最後の切り札」として、この手法を覚えておいてほしい。
データベース設計に「銀の弾丸」はない。でも、引き出しの多さは、君を困難から救ってくれるはずだ。
それじゃ、また現場で会おう。何か詰まったら、いつでも聞きに来てくれ。
コメント