PostgreSQLアーキテクチャ入門
PostgreSQLは30年以上活発に開発されてきたオープンソースのオブジェクトリレーショナルデータベース管理システムです。バックエンド開発者にとって、PostgreSQLの仕組みを理解することは、より高速なクエリの作成、より良いスキーマの設計、パフォーマンス問題の効果的なトラブルシューティングに役立ちます。
コアアーキテクチャは複数のレイヤーが協調して動作する構成になっています。最上位では、クライアントアプリケーションがPostgreSQLワイヤープロトコルを使用してネットワークソケット経由で接続します。接続はまずpostmasterプロセスによって受信され、クライアント接続ごとに新しいバックエンドプロセスがフォークされます。この接続ごとのプロセスモデルは強力な分離を提供しますが、同時実行性の高いアプリケーションでは接続プーリング(PgBouncerなど)を使用する必要があります。
クエリがバックエンドプロセスに到達すると、クエリプロセッサを通過します: パーサーが構文をチェックし、アナライザー/リライタールールを適用して権限を検証し、プランナーが最適な実行プランを生成し、エクスペキュータがそのプランをストレージ層に対して実行します。ストレージ層は、行が読み書きされるヒープファイル構造を使用し、別のインデックスファイル(通常はB-tree)がインデックス化された列の高速検索を提供します。
正規化されたリレーショナルスキーマの設計
リレーショナル設計とは、冗長性を最小限に抑え、データの整合性を保護するためにテーブルを整理する手法です。基礎となる概念は正規化であり、データを関連するテーブルに分割する方法を導くルール群(正規形)です。
最も一般的に適用される正規形は第1正規形(1NF)、第2正規形(2NF)、第3正規形(3NF)です。第1正規形では、各カラムがアトミックな値を保持することが求められます — 単一のセル内に配列やカンマ区切りのリストを含めることはできません。第2正規形は1NFに基づき、すべての非キー列が主キー全体に依存することを要求します。これは主に複合キーの場合に重要です。第3正規形はさらに進み、非キー列が他の非キー列に依存してはいけません。
ブログ記事とその著者、タグを保存する必要がある実用的なシナリオを考えてみましょう。非正規化されたアプローチでは、すべてを1つのテーブルに格納しますが、これにより更新異常が発生します — 著者がメールアドレスを変更した場合、その著者が書いたすべての行を更新しなければなりません。正規化された設計では、これを外部キーを持つ別のテーブルに分割します。
post_tagsテーブルは、記事とタグの多対多関係を解決する結合テーブルです。SERIALが自動増分整数を提供し、REFERENCESが外部キー制約を定義し、ON DELETE CASCADEが親が削除されたときに結合行を自動的に削除することに注目してください。
データ型と制約
PostgreSQLは基本的なINTEGERやVARCHARを超える豊富な型システムを提供しています。バックエンド開発者にとって、特に便利な型には、タイムゾーン認識付きのタイムスタンプ用のTIMESTAMPTZ、インデックス機能を備えた半構造化データ保存用のJSONB、グローバル一意識別子用のUUID、真偽フラグ用のBOOLEANなどがあります。
制約はアプリケーションコードのみに依存するのではなく、データベースレベルでデータ整合性を強制します。一般的な制約には、NOT NULL、UNIQUE、CHECK、FOREIGN KEY、PRIMARY KEYがあります。制約を使用することで、バグのあるアプリケーションが無効な値を挿入しようとしても、データが有効な状態を維持できます。
NUMERIC(10,2)は正確な10進数値を保存し、浮動小数点エラーが許容されない金額に最適です。CHECK制約により、priceとstockが負になることは決してありません。metadataに対するDEFAULT句により、新しい行はNULLではなく空のJSONオブジェクトを自動的に取得します。
よくある設計ミス
よくある間違いの1つは、長さ制限なしでVARCHARを使用することで、予期せず巨大な行につながる可能性があります。もう1つは、列が本当に無制限の長さを必要とするかどうかを考慮せず、あらゆる場所でTEXTを選択することです — 制約を明示することでバグをより早期に発見できます。開発者は外部キーカラムのインデックスを忘れがちで、これにより大規模なテーブルでのJOIN操作とCASCADE削除が遅くなります。
過度な正規化は反対の落とし穴です: データを小さすぎるテーブルに分割しすぎると、クエリが過剰なJOINを必要とする可能性があります。読み込み中心のワークロードでは、戦略的な非正規化やマテリアライズドビューが正しいトレードオフかもしれません。目標は、特定のアクセスパターンに合わせたバランスを見つけることです。
まとめ
PostgreSQLのマルチプロセスアーキテクチャとパーサープランナーエクスペキュータパイプラインは、予測可能なパフォーマンス特性を提供します。1NF、2NF、3NFによる正規化されたリレーショナル設計は冗長性を減らし更新異常を防ぎ、外部キーと結合テーブルが複雑な関係を処理します。PostgreSQLの豊富な型システムと制約サポートにより、スキーマレベルでデータ整合性を強制し、エラーがアプリケーションコードに到達する前に検出できます。次のレッスンでは、スキーマ設計からこれらの構造に対する効率的なクエリの作成へと進みます。
レッスンのチェックポイント