【実務・中級編】 テーブル継承とFDWの併用 – PostgreSQL

「巨大なテーブル、どう分割する?」——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の力技だ。
複雑なサーバー構成を組まざるを得ないときや、既存のレガシーなデータアーカイブを統合したいとき、この知識は君の武器になる。

でも、「複雑さは悪」だ。まずは宣言的パーティショニングで解決できないか検討し、どうしても物理的な分離が必要なときの「最後の切り札」として、この手法を覚えておいてほしい。

データベース設計に「銀の弾丸」はない。でも、引き出しの多さは、君を困難から救ってくれるはずだ。

それじゃ、また現場で会おう。何か詰まったら、いつでも聞きに来てくれ。

コメント

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