PostgreSQLの型システムを使いこなす:DOMAINとENUMがもたらす「型安全」という名の安らぎ
PostgreSQLを長年触っていると、ふと「なぜ標準的なデータ型だけで済ませようとしていたのか」と自問する瞬間が来ます。`text`や`int`で構築されたスキーマは柔軟ですが、アプリケーション層でのバリデーション漏れが、巡り巡ってデータベースの整合性を蝕むリスクを常に孕んでいるからです。
今日は、PostgreSQLの強力な武器である`CREATE DOMAIN`と`CREATE TYPE (ENUM)`について、単なる構文解説ではなく、現場で泣きを見ないための「内部的な振る舞い」と「設計の勘所」について語りたいと思います。
—
1. ENUM型:便利さと引き換えに背負う「設計の呪縛」
`CREATE TYPE status AS ENUM (‘draft’, ‘published’, ‘archived’);`
これ、本当に便利ですよね。アプリ側でもDB側でも同じ名前でステータスを扱える。しかし、経験豊富なエンジニアなら一度は頭を抱えたことがあるはずです。「列挙型の追加・削除のコスト」と「実行計画への影響」について。
内部的な挙動
PostgreSQLのENUMは、内部的には`pg_enum`カタログで定義されたOID(オブジェクトID)として管理されています。この値はソート順が定義可能で、列挙順序がディスク上の物理的な順序に影響します。
注意すべき落とし穴:ALTER TYPEの恐怖
最も危険なのは、`ALTER TYPE … ADD VALUE …`です。
- ロックの競合: `ADD VALUE`自体は排他的なロックを要求します。高トラフィックなテーブルでこれを実行すると、その後のクエリが待機列に並び、一気にシステムのレスポンスが劣化します。
- 物理レイアウトの不整合: 列挙型を頻繁に変更するような設計は、本質的に「状態管理が不安定」であることを示唆しています。もしそのステータスが「将来的に増える可能性がある」なら、ENUMではなく、`lookup table`(外部キー参照)を使うのがデータベースエンジニアとしての誠実な設計です。
—
2. DOMAIN:型に「意志」を込める
`CREATE DOMAIN`は、既存の型に対して制約(CHECK制約)を付与した「サブタイプ」を作成する機能です。`text`や`int`にビジネスロジックの断片を埋め込める、非常にエレガントな仕組みです。
例えば、郵便番号やメールアドレス、あるいは「必ずプラスの値であること」を強制したいIDなど。
CREATE DOMAIN postal_code AS text
CHECK (VALUE ~ ‘^\d{3}-\d{4}$’);
パフォーマンスへの影響:制約のオーバーヘッド
ここでよく議論になるのが、「ドメイン制約は通常のCHECK制約と何が違うのか」という点です。
実は、ドメインの制約は対象の列が参照されるたびに評価されます。大量のレコードをバルクインサートする際、このドメイン制約がボトルネックになることがあります。特に複雑な正規表現をドメインに詰め込むと、CPU負荷が指数関数的に増大します。
トラブルシューティングのヒント
ドメインを使用したテーブルでパフォーマンスが出ない場合、`EXPLAIN ANALYZE`で実行計画を追うのも大切ですが、「ドメインの制約が暗黙的に走っていないか」を疑ってください。
もしドメイン制約がボトルネックなら、ドメインを解体して、必要な時だけ制約を付与する設計への回帰を検討すべきです。あくまで「型」としての制約は、ビジネス上の「ガードレール」として使い、極端な高負荷が予想される箇所では、DBの型安全性とアプリケーション側のバリデーションのバランスを取る勇気が必要です。
—
3. プロの視点:どちらを選ぶべきか
私の現場での判断基準はシンプルです。
1. 「概念的に不変なリスト」ならENUM:
- 例:曜日、性別(定義による)、HTTPメソッドなど。
- 定義が変わる可能性がほぼゼロである場合のみ使用します。
2. 「データが持つべき特性」ならDOMAIN:
- 例:通貨単位、特定のフォーマット、許容範囲。
- データの整合性をアプリケーションに依存させず、データベース層で担保したい「境界値」には迷わずドメインを使います。
—
最後に:データベースは「裏切らない」
PostgreSQLの型システムは、開発者が「何を保持したいのか」という意図を明確にするための言語です。`text`型で全てを表現するのは、白紙のキャンバスに絵を描くようなものですが、ドメインやENUMを駆使することは、そこに正しい「額縁」をはめる作業に似ています。
額縁がしっかりしていれば、中の絵(データ)が崩れることはありません。
ぜひ皆さんのスキーマ設計に、これらの機能を「やりすぎない程度に」取り入れてみてください。型が語りかけてくるようになれば、あなたのDBエンジニアとしてのスキルは、また一段階上の領域に達しているはずです。
それでは、また次回の深掘りでお会いしましょう。Happy Querying!
コメント