変更要約: 初版(主題S3・S3.1〜S3.3)
3.2データ定義とDBオブジェクト(データ型・制約・インデックス・ビュー等)
テーブルを設計・変更するCREATE TABLE・ALTER TABLE・DROP TABLE、主要なデータ型(INTEGER/BIGINT/NUMERIC/VARCHAR/TEXT/BOOLEAN/DATE/TIMESTAMP/JSON/JSONB)、データの整合性を守る制約(PRIMARY KEY・FOREIGN KEY・UNIQUE・CHECK・NOT NULL)、検索を高速化するインデックス、ビュー・マテリアライズドビュー、トリガー、シーケンス、スキーマ、テーブル空間、パーティション、PL/pgSQLによる関数、ストリーミング/ロジカルレプリケーションの基礎知識を学びます。
SQLで問い合わせるためには、まずデータを正しい形で保管する器を設計する必要があります。PostgreSQLはテーブルという基本単位に加え、ビュー・トリガー・シーケンスなど多様なデータベースオブジェクトを提供しており、それぞれが「整合性を守る」「重複を防ぐ」「よく使う問い合わせを再利用する」といった異なる役割を担います。この節では設計の基礎から運用寄りのオブジェクトまでを一望します。
3.2.1テーブル定義・データ型・制約
- CREATE TABLE=新規テーブル定義(
CREATE TABLE t (id INTEGER PRIMARY KEY, name VARCHAR(50)))。ALTER TABLE=列追加・型変更・制約追加等(ALTER TABLE t ADD COLUMN email TEXT)。DROP TABLE=テーブルごと削除(データも構造も消える破壊的操作)。 - 主なデータ型=整数のINTEGER(4バイト)・BIGINT(8バイト、より大きな範囲)/小数のNUMERIC(任意精度・金額計算向け)/文字列のVARCHAR(可変長・上限指定可)・TEXT(無制限長)/真偽のBOOLEAN/日時のDATE(日付のみ)・TIMESTAMP(日時、タイムゾーン付きは
TIMESTAMP WITH TIME ZONE)。 - JSON=JSONデータをテキストとしてそのまま保存(入力の見た目を保持)。JSONB=バイナリ形式で解析済み保存(重複キー排除・キー順不定だが、検索・インデックス作成が速い)。実務ではJSONBが推奨されることが多い。
- 制約=PRIMARY KEY(一意性+NOT NULLを兼ねる主キー)/FOREIGN KEY(他テーブルの主キーを参照し参照整合性を強制)/UNIQUE(重複禁止だがNULLは複数許容)/CHECK(
CHECK (age >= 0)のような任意条件)/NOT NULL(NULL値を禁止)。
3.2.2インデックス・ビュー・その他のDBオブジェクト
- インデックス=検索を高速化する補助構造(
CREATE INDEX idx_name ON t (col))。書き込み時の更新コストとのトレードオフがある。ビュー=クエリ結果を仮想的な表として保存(CREATE VIEW v AS SELECT ...。実データは持たず参照のたびに再実行)。マテリアライズドビュー=ビューの結果を実体として保存し、REFRESH MATERIALIZED VIEWで更新(高速だが最新性はリフレッシュ次第)。 - トリガー=特定のイベント(INSERT/UPDATE/DELETE)発生時に自動的に関数を実行する仕組み(
CREATE TRIGGER)。シーケンス=自動増分の連番値を生成するオブジェクト(CREATE SEQUENCE、主キーの自動採番SERIAL型の内部実装)。スキーマ=テーブル等をまとめる名前空間(schema.tableの形で修飾、既定はpublic)。 - テーブル空間(TABLESPACE)=テーブルやインデックスの物理的な格納先ディレクトリを指定する仕組み(
CREATE TABLESPACE、ディスク分散に利用)。パーティション=1つの論理テーブルを複数の物理テーブルに分割して管理(範囲・リスト等の方式。大量データの管理・検索効率化)。 - 関数/プロシージャ=PL/pgSQL等の手続き型言語でロジックをDB内に実装(
CREATE FUNCTION)。トリガーの実行本体としても使われる。ストリーミング/ロジカルレプリケーション=基礎知識として、変更をWALベースで別サーバへ転送しコピーを維持する仕組みがある、という概念レベルの理解にとどめる(構築・監視・障害復旧はGold範囲)。
「PRIMARY KEYは一意性+NOT NULL・UNIQUEはNULL複数可」「ビューは仮想(都度再実行)・マテリアライズドビューは実体保存でREFRESHが必要」「JSONBは解析済みバイナリで検索が速い・JSONはテキスト保持」「FOREIGN KEYは参照整合性を強制」が最頻出です。トリガー・シーケンス・テーブル空間・パーティションといった各DBオブジェクトの役割の一言説明を問う設問も定番です。
新しいECサイトのデータベースを設計する場面を想定して、各オブジェクトがどう連携するかを追ってみましょう。まずCREATE TABLE products (id SERIAL PRIMARY KEY, name VARCHAR(100) NOT NULL, price NUMERIC(10,2) CHECK (price >= 0), attributes JSONB)のようにテーブルを作ると、id列は内部で自動生成されるシーケンス(products_id_seq)から採番され、priceには0以上というCHECK制約、商品の可変的な追加情報(色・サイズ等)はJSONB列に柔軟に格納します。注文テーブルordersにはproduct_id INTEGER REFERENCES products(id)のようにFOREIGN KEYを張り、存在しない商品IDへの注文を防ぎます。検索が頻発するorders.product_id列にはCREATE INDEX idx_orders_product ON orders (product_id)でインデックスを張ると結合検索が高速化しますが、書き込みのたびにインデックスも更新されるコストとのバランスを考える必要があります。集計処理が重い「商品別の月間売上ランキング」は、毎回集計するとコストが高いためマテリアライズドビューとしてCREATE MATERIALIZED VIEW monthly_sales AS SELECT ...で作成し、深夜バッチでREFRESH MATERIALIZED VIEW monthly_salesを実行して最新化する設計が定石です(通常のビューはSELECTのたびに元テーブルへ再実行されるため、重い集計には不向き)。在庫が0になったら自動的に通知テーブルへ記録したい場合は、productsへのUPDATE時に発火するトリガーと、その実処理を書いたPL/pgSQL関数を組み合わせます。テーブルが年月ごとに巨大化するordersはパーティションで年月ごとの物理テーブルに分割すると、古いデータの検索・削除が効率化されます。レプリケーションについては基礎知識として、本番サーバの変更をWALベースでストリーミング転送し、読み取り専用の複製サーバを維持できるという概念を押さえておけば十分で、実際の構築手順やパラメータチューニングはこの試験の範囲外です。
| オブジェクト | 役割 | 備考 |
|---|---|---|
| ビュー | クエリを仮想的な表として保存 | 参照のたびに再実行・実データ無し |
| マテリアライズドビュー | 結果を実体として保存 | REFRESH で更新・重い集計向き |
| トリガー | イベント発生時に関数を自動実行 | 本体はPL/pgSQL関数で実装 |
| シーケンス | 自動増分の連番を生成 | SERIAL型の内部実装 |
ひっかけ: 「ビューはクエリ結果を保存するので、元テーブルが変わっても表示は更新されない」は誤りです。通常のビューは参照のたびに元のSELECTを再実行するため常に最新の結果を返し、逆に更新のためにREFRESHが必要なのはマテリアライズドビューです。また「UNIQUE制約が付いた列にはNULLを1つも入れられない」も誤り=UNIQUEは重複を禁止するがNULLは複数許容(NULL同士は同値とみなされない)します。NULLも禁止したい場合はNOT NULLを併用します。
3.2.3この節のまとめ
- CREATE/ALTER/DROP TABLEでテーブル管理。PRIMARY KEY=一意+NOT NULL・UNIQUE=NULL複数可・FOREIGN KEY=参照整合性・CHECK=任意条件
- JSONB=解析済みバイナリで高速検索・JSONはテキスト保持。ビュー=仮想(都度再実行)・マテリアライズドビュー=実体保存+REFRESH要
- トリガー=イベント駆動で関数実行・シーケンス=連番生成・パーティション=物理分割。レプリケーションはSilverでは基礎概念のみ
進捗の記録にはログインが必要です。
理解度チェック
(軽い確認用)Q1. ある列に「重複した値は許さないが、値が未入力(NULL)の行は複数存在してよい」という制約を課したい。適切な制約はどれか。
Q2. 毎回の集計コストが高い「日別売上サマリ」を高速に参照したい。多少データが古くても構わないので、実体として結果を保存しておき、夜間バッチで明示的に更新する方式にしたい。どのオブジェクトが適切か。
Q3. 商品情報の一部(色・サイズなど可変的な属性)を柔軟に格納したい。検索性能も重視する場合、最も適したデータ型はどれか。

