PostgreSQL完全ガイド
PostgreSQL完全ガイド
Section titled “PostgreSQL完全ガイド”PostgreSQLの実践的な使い方を、実務で使える実装例とベストプラクティスとともに詳しく解説します。
1. PostgreSQLとは
Section titled “1. PostgreSQLとは”PostgreSQLの特徴
Section titled “PostgreSQLの特徴”PostgreSQLは、オープンソースのリレーショナルデータベース管理システム(RDBMS)です。
PostgreSQLの特徴 ├─ オープンソース(無料) ├─ 標準SQLへの準拠が高い ├─ 高度な機能(JSON型、配列型、全文検索など) ├─ 拡張性が高い(拡張機能が豊富) └─ ACID特性を完全にサポートなぜPostgreSQLを選ぶのか
Section titled “なぜPostgreSQLを選ぶのか”PostgreSQLを選ぶべき場合:
- 複雑なデータ型が必要(JSON、配列、全文検索など)
- 標準SQLへの準拠が重要
- オープンソースを希望
- 高度な機能が必要
PostgreSQLを選ばないべき場合:
- シンプルなWebアプリケーション(MySQLの方が適している場合がある)
- メモリ使用量を最小限に抑えたい場合
2. PostgreSQLのインストールとセットアップ
Section titled “2. PostgreSQLのインストールとセットアップ”macOSでのインストール
Section titled “macOSでのインストール”# Homebrewを使用brew install postgresql@15
# サービスを開始brew services start postgresql@15
# PostgreSQLに接続psql postgresLinuxでのインストール
Section titled “Linuxでのインストール”# Ubuntu/Debiansudo apt-get updatesudo apt-get install postgresql postgresql-contrib
# サービスを開始sudo systemctl start postgresqlsudo systemctl enable postgresql
# PostgreSQLに接続sudo -u postgres psqlWindowsでのインストール
Section titled “Windowsでのインストール”- PostgreSQL公式サイトからインストーラーをダウンロード
- インストーラーを実行し、指示に従ってインストール
- pgAdminまたはコマンドプロンプトから接続
-- データベースの作成CREATE DATABASE myapp;
-- ユーザーの作成CREATE USER myuser WITH PASSWORD 'mypassword';
-- 権限の付与GRANT ALL PRIVILEGES ON DATABASE myapp TO myuser;
-- データベースに接続\c myapp3. PostgreSQLの高度なデータ型
Section titled “3. PostgreSQLの高度なデータ型”JSON型とJSONB型
Section titled “JSON型とJSONB型”PostgreSQLは、JSONデータをネイティブにサポートしています。
-- JSON型のテーブル作成CREATE TABLE products ( id SERIAL PRIMARY KEY, name VARCHAR(255) NOT NULL, attributes JSONB, metadata JSON);
-- JSONデータの挿入INSERT INTO products (name, attributes, metadata)VALUES ( 'Laptop', '{"color": "black", "weight": 2.5, "specs": {"cpu": "Intel i7", "ram": "16GB"}}', '{"tags": ["electronics", "computers"], "rating": 4.5}');
-- JSONクエリ-- JSONB型の方が高速(バイナリ形式)SELECT name, attributes->>'color' AS color, attributes->'specs'->>'cpu' AS cpu, metadata->'tags'->>0 AS first_tagFROM productsWHERE attributes->>'color' = 'black';
-- JSONBのインデックス作成(GINインデックス)CREATE INDEX idx_attributes ON products USING GIN (attributes);JSON型 vs JSONB型:
- JSON型: テキスト形式、挿入が高速、クエリが低速
- JSONB型: バイナリ形式、挿入が低速、クエリが高速、インデックス対応
-- 配列型のテーブル作成CREATE TABLE users ( id SERIAL PRIMARY KEY, name VARCHAR(255) NOT NULL, email VARCHAR(255) UNIQUE NOT NULL, tags TEXT[], scores INTEGER[]);
-- 配列データの挿入INSERT INTO users (name, email, tags, scores)VALUES ( 'Alice', 'alice@example.com', ARRAY['developer', 'designer'], ARRAY[85, 90, 88]);
-- 配列クエリ-- 特定の要素を含む配列を検索SELECT * FROM usersWHERE 'developer' = ANY(tags);
-- 配列の要素数を取得SELECT name, array_length(tags, 1) AS tag_countFROM users;
-- 配列の結合SELECT name, array_to_string(tags, ', ') AS tags_stringFROM users;全文検索(Full-Text Search)
Section titled “全文検索(Full-Text Search)”-- 全文検索用のテーブル作成CREATE TABLE articles ( id SERIAL PRIMARY KEY, title VARCHAR(255) NOT NULL, content TEXT NOT NULL, search_vector tsvector);
-- tsvectorカラムの自動更新(トリガー)CREATE OR REPLACE FUNCTION update_search_vector()RETURNS TRIGGER AS $$BEGIN NEW.search_vector := setweight(to_tsvector('english', COALESCE(NEW.title, '')), 'A') || setweight(to_tsvector('english', COALESCE(NEW.content, '')), 'B'); RETURN NEW;END;$$ LANGUAGE plpgsql;
CREATE TRIGGER tsvectorupdate BEFORE INSERT OR UPDATEON articles FOR EACH ROWEXECUTE FUNCTION update_search_vector();
-- データの挿入INSERT INTO articles (title, content)VALUES ( 'PostgreSQL Guide', 'This is a comprehensive guide to PostgreSQL database management.');
-- 全文検索クエリSELECT title, contentFROM articlesWHERE search_vector @@ to_tsquery('english', 'guide & database');
-- GINインデックスの作成(全文検索の高速化)CREATE INDEX idx_search_vector ON articles USING GIN (search_vector);4. パーティショニング
Section titled “4. パーティショニング”範囲パーティショニング(Range Partitioning)
Section titled “範囲パーティショニング(Range Partitioning)”-- 親テーブルの作成CREATE TABLE orders ( id SERIAL, user_id INTEGER NOT NULL, order_date DATE NOT NULL, amount DECIMAL(10, 2) NOT NULL, PRIMARY KEY (id, order_date)) PARTITION BY RANGE (order_date);
-- パーティションの作成CREATE TABLE orders_2024_q1 PARTITION OF ordersFOR VALUES FROM ('2024-01-01') TO ('2024-04-01');
CREATE TABLE orders_2024_q2 PARTITION OF ordersFOR VALUES FROM ('2024-04-01') TO ('2024-07-01');
CREATE TABLE orders_2024_q3 PARTITION OF ordersFOR VALUES FROM ('2024-07-01') TO ('2024-10-01');
CREATE TABLE orders_2024_q4 PARTITION OF ordersFOR VALUES FROM ('2024-10-01') TO ('2025-01-01');
-- データの挿入(自動的に適切なパーティションに挿入される)INSERT INTO orders (user_id, order_date, amount)VALUES (1, '2024-02-15', 100.00);
-- パーティションの確認SELECT * FROM orders_2024_q1;リストパーティショニング(List Partitioning)
Section titled “リストパーティショニング(List Partitioning)”-- 親テーブルの作成CREATE TABLE users ( id SERIAL, name VARCHAR(255) NOT NULL, country VARCHAR(2) NOT NULL, email VARCHAR(255) NOT NULL, PRIMARY KEY (id, country)) PARTITION BY LIST (country);
-- パーティションの作成CREATE TABLE users_jp PARTITION OF usersFOR VALUES IN ('JP');
CREATE TABLE users_us PARTITION OF usersFOR VALUES IN ('US');
CREATE TABLE users_uk PARTITION OF usersFOR VALUES IN ('UK');
-- デフォルトパーティション(その他の国)CREATE TABLE users_other PARTITION OF usersDEFAULT;ハッシュパーティショニング(Hash Partitioning)
Section titled “ハッシュパーティショニング(Hash Partitioning)”-- 親テーブルの作成CREATE TABLE products ( id SERIAL, name VARCHAR(255) NOT NULL, category_id INTEGER NOT NULL, price DECIMAL(10, 2) NOT NULL, PRIMARY KEY (id, category_id)) PARTITION BY HASH (category_id);
-- パーティションの作成(4つのパーティション)CREATE TABLE products_0 PARTITION OF productsFOR VALUES WITH (MODULUS 4, REMAINDER 0);
CREATE TABLE products_1 PARTITION OF productsFOR VALUES WITH (MODULUS 4, REMAINDER 1);
CREATE TABLE products_2 PARTITION OF productsFOR VALUES WITH (MODULUS 4, REMAINDER 2);
CREATE TABLE products_3 PARTITION OF productsFOR VALUES WITH (MODULUS 4, REMAINDER 3);5. レプリケーション
Section titled “5. レプリケーション”ストリーミングレプリケーション(Streaming Replication)
Section titled “ストリーミングレプリケーション(Streaming Replication)”# マスターサーバーの設定(postgresql.conf)wal_level = replicamax_wal_senders = 3max_replication_slots = 3
# pg_hba.confにレプリケーション設定を追加host replication replicator 192.168.1.100/32 md5# レプリカサーバーの設定# 1. ベースバックアップの取得pg_basebackup -h master_host -D /var/lib/postgresql/data -U replicator -v -P -W
# 2. recovery.confの作成(PostgreSQL 12以降はpostgresql.confに設定)primary_conninfo = 'host=master_host port=5432 user=replicator password=replicator_password'論理レプリケーション(Logical Replication)
Section titled “論理レプリケーション(Logical Replication)”-- パブリッシャーの設定CREATE PUBLICATION my_publication FOR TABLE users, orders;
-- サブスクライバーの設定CREATE SUBSCRIPTION my_subscriptionCONNECTION 'host=publisher_host port=5432 dbname=mydb user=replicator password=password'PUBLICATION my_publication;6. インデックスの最適化
Section titled “6. インデックスの最適化”B-treeインデックス
Section titled “B-treeインデックス”-- 基本的なB-treeインデックスCREATE INDEX idx_users_email ON users(email);
-- 複合インデックスCREATE INDEX idx_orders_user_date ON orders(user_id, order_date);
-- 部分インデックス(条件付きインデックス)CREATE INDEX idx_active_users ON users(email)WHERE status = 'active';GINインデックス(Generalized Inverted Index)
Section titled “GINインデックス(Generalized Inverted Index)”-- JSONB型のインデックスCREATE INDEX idx_products_attributes ON products USING GIN (attributes);
-- 配列型のインデックスCREATE INDEX idx_users_tags ON users USING GIN (tags);
-- 全文検索のインデックスCREATE INDEX idx_articles_search ON articles USING GIN (search_vector);GiSTインデックス(Generalized Search Tree)
Section titled “GiSTインデックス(Generalized Search Tree)”-- 空間データのインデックス(PostGIS拡張を使用)CREATE EXTENSION IF NOT EXISTS postgis;
CREATE TABLE locations ( id SERIAL PRIMARY KEY, name VARCHAR(255), location GEOGRAPHY(POINT, 4326));
CREATE INDEX idx_locations_geo ON locations USING GIST (location);7. パフォーマンス最適化
Section titled “7. パフォーマンス最適化”EXPLAIN ANALYZEの使用
Section titled “EXPLAIN ANALYZEの使用”-- クエリプランの確認EXPLAIN ANALYZESELECT u.name, COUNT(o.id) AS order_countFROM users uLEFT JOIN orders o ON u.id = o.user_idWHERE u.created_at > '2024-01-01'GROUP BY u.id, u.nameORDER BY order_count DESCLIMIT 10;統計情報の更新
Section titled “統計情報の更新”-- 統計情報の手動更新ANALYZE users;ANALYZE orders;
-- 特定のカラムの統計情報を更新ANALYZE users (email, created_at);バキューム(VACUUM)
Section titled “バキューム(VACUUM)”-- 通常のバキュームVACUUM users;
-- 完全なバキューム(テーブルをロック)VACUUM FULL users;
-- バキュームとアナライズを同時に実行VACUUM ANALYZE users;
-- 自動バキュームの設定(postgresql.conf)autovacuum = onautovacuum_naptime = 1min8. 拡張機能(Extensions)
Section titled “8. 拡張機能(Extensions)”よく使われる拡張機能
Section titled “よく使われる拡張機能”-- UUID生成CREATE EXTENSION IF NOT EXISTS "uuid-ossp";SELECT uuid_generate_v4();
-- 全文検索(日本語対応)CREATE EXTENSION IF NOT EXISTS pg_trgm;CREATE INDEX idx_users_name_trgm ON users USING GIN (name gin_trgm_ops);
-- 空間データ(PostGIS)CREATE EXTENSION IF NOT EXISTS postgis;
-- 統計情報の拡張CREATE EXTENSION IF NOT EXISTS pg_stat_statements;
-- 暗号化CREATE EXTENSION IF NOT EXISTS pgcrypto;9. トランザクションとロック
Section titled “9. トランザクションとロック”トランザクションの分離レベル
Section titled “トランザクションの分離レベル”-- 分離レベルの設定BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED;
-- 読み取り専用トランザクションBEGIN TRANSACTION READ ONLY;
-- デフォルトの分離レベル(READ COMMITTED)BEGIN;SELECT * FROM users WHERE id = 1;COMMIT;ロックの種類
Section titled “ロックの種類”-- 行レベルロックBEGIN;SELECT * FROM users WHERE id = 1 FOR UPDATE;-- 他のトランザクションはこの行を更新できないUPDATE users SET name = 'New Name' WHERE id = 1;COMMIT;
-- 共有ロック(読み取り専用)BEGIN;SELECT * FROM users WHERE id = 1 FOR SHARE;COMMIT;
-- テーブルロックLOCK TABLE users IN EXCLUSIVE MODE;10. バックアップとリストア
Section titled “10. バックアップとリストア”pg_dumpによるバックアップ
Section titled “pg_dumpによるバックアップ”# データベース全体のバックアップpg_dump -h localhost -U postgres -d mydb -F c -f backup.dump
# テーブルのみのバックアップpg_dump -h localhost -U postgres -d mydb -t users -t orders -f tables.dump
# スキーマのみのバックアップpg_dump -h localhost -U postgres -d mydb -s -f schema.dump
# データのみのバックアップpg_dump -h localhost -U postgres -d mydb -a -f data.dumppg_restoreによるリストア
Section titled “pg_restoreによるリストア”# カスタム形式のリストアpg_restore -h localhost -U postgres -d mydb -c backup.dump
# テーブルのリストアpg_restore -h localhost -U postgres -d mydb -t users backup.dump継続的アーカイブ(WALアーカイブ)
Section titled “継続的アーカイブ(WALアーカイブ)”# postgresql.confの設定wal_level = replicaarchive_mode = onarchive_command = 'cp %p /path/to/archive/%f'11. セキュリティ
Section titled “11. セキュリティ”ユーザーとロールの管理
Section titled “ユーザーとロールの管理”-- ロールの作成CREATE ROLE app_user WITH LOGIN PASSWORD 'secure_password';
-- 権限の付与GRANT SELECT, INSERT, UPDATE, DELETE ON users TO app_user;GRANT USAGE, SELECT ON SEQUENCE users_id_seq TO app_user;
-- スキーマへのアクセス権限GRANT USAGE ON SCHEMA public TO app_user;
-- 権限の取り消しREVOKE DELETE ON users FROM app_user;行レベルセキュリティ(RLS)
Section titled “行レベルセキュリティ(RLS)”-- RLSの有効化ALTER TABLE users ENABLE ROW LEVEL SECURITY;
-- ポリシーの作成CREATE POLICY user_policy ON usersFOR ALLTO app_userUSING (user_id = current_user_id());
-- ポリシーの確認SELECT * FROM pg_policies WHERE tablename = 'users';12. 実践的なベストプラクティス
Section titled “12. 実践的なベストプラクティス”-- テーブル名: 複数形、スネークケースCREATE TABLE user_profiles (...);
-- カラム名: スネークケースCREATE TABLE users ( id SERIAL PRIMARY KEY, first_name VARCHAR(255), created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP);
-- インデックス名: idx_テーブル名_カラム名CREATE INDEX idx_users_email ON users(email);マイグレーション管理
Section titled “マイグレーション管理”-- バージョン管理テーブルの作成CREATE TABLE schema_migrations ( version VARCHAR(255) PRIMARY KEY, applied_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP);
-- マイグレーションの適用BEGIN;-- マイグレーションSQLINSERT INTO schema_migrations (version) VALUES ('001_create_users');COMMIT;-- スロークエリのログ設定(postgresql.conf)log_min_duration_statement = 1000 -- 1秒以上かかるクエリをログ
-- 接続数の確認SELECT count(*) FROM pg_stat_activity;
-- データベースサイズの確認SELECT pg_size_pretty(pg_database_size('mydb'));
-- テーブルサイズの確認SELECT schemaname, tablename, pg_size_pretty(pg_total_relation_size(schemaname||'.'||tablename)) AS sizeFROM pg_tablesWHERE schemaname = 'public'ORDER BY pg_total_relation_size(schemaname||'.'||tablename) DESC;13. よくある問題と解決方法
Section titled “13. よくある問題と解決方法”問題1: 接続数が上限に達している
Section titled “問題1: 接続数が上限に達している”-- 接続数の確認SELECT count(*) FROM pg_stat_activity;
-- 最大接続数の確認SHOW max_connections;
-- 接続プールの使用を推奨(PgBouncerなど)問題2: ディスク容量不足
Section titled “問題2: ディスク容量不足”-- データベースサイズの確認SELECT pg_size_pretty(pg_database_size('mydb'));
-- 不要なデータの削除とバキュームDELETE FROM old_logs WHERE created_at < NOW() - INTERVAL '1 year';VACUUM FULL old_logs;問題3: クエリが遅い
Section titled “問題3: クエリが遅い”-- スロークエリの確認SELECT query, calls, total_time, mean_timeFROM pg_stat_statementsORDER BY mean_time DESCLIMIT 10;
-- インデックスの確認SELECT tablename, indexname, idx_scanFROM pg_stat_user_indexesWHERE idx_scan = 0; -- 使用されていないインデックスPostgreSQL完全ガイドのポイント:
- 高度なデータ型: JSON、配列、全文検索など
- パーティショニング: 大規模データの効率的な管理
- レプリケーション: 高可用性の実現
- インデックス最適化: パフォーマンスの向上
- 拡張機能: 豊富な機能拡張
- セキュリティ: ユーザー管理、RLS
- バックアップ: データ保護
- 監視: パフォーマンス管理
適切なPostgreSQLの使用により、スケーラブルで信頼性の高いアプリケーションを構築できます。