PostgreSQL
世界で最も先進的なオープンソースリレーショナルデータベース。ACID準拠、JSON対応、全文検索機能を内蔵。Stack Overflow調査で2年連続開発者人気首位。
PostgreSQL
PostgreSQLは、高度な機能と拡張性を持つオープンソースのリレーショナルデータベース管理システム(RDBMS)です。30年以上の開発歴史を持ち、ACID準拠、高い並行性、豊富なデータ型、強力な検索機能を提供しています。
主な特徴
高度なSQL機能
- SQL標準への高い準拠率
- ウィンドウ関数、CTE(共通テーブル式)、LATERAL結合
- 配列、JSON/JSONB、hstore、地理空間データ型
- 正規表現とフルテキスト検索
拡張性とプラグイン
- カスタム関数、集約関数、演算子の作成
- 多言語での関数作成(PL/pgSQL、Python、Perl、Tcl等)
- 豊富な拡張モジュール(PostGIS、pg_stat_statements等)
エンタープライズ機能
- MVCC(多版本並行性制御)
- 論理レプリケーション・ストリーミングレプリケーション
- パーティショニング(レンジ、リスト、ハッシュ)
- 行レベルセキュリティ(RLS)
インストール
Ubuntu/Debian
# 公式APTリポジトリの追加
sudo sh -c 'echo "deb http://apt.postgresql.org/pub/repos/apt $(lsb_release -cs)-pgdg main" > /etc/apt/sources.list.d/pgdg.list'
wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | sudo apt-key add -
sudo apt-get update
# PostgreSQL 16のインストール
sudo apt-get install postgresql-16 postgresql-client-16
CentOS/RHEL
# 公式YUMリポジトリの追加
sudo dnf install -y https://download.postgresql.org/pub/repos/yum/reporpms/EL-9-x86_64/pgdg-redhat-repo-latest.noarch.rpm
# PostgreSQL 16のインストール
sudo dnf install -y postgresql16-server postgresql16
sudo /usr/pgsql-16/bin/postgresql-16-setup initdb
sudo systemctl enable postgresql-16
sudo systemctl start postgresql-16
Docker
# PostgreSQL 16の起動
docker run --name postgres-db \
-e POSTGRES_PASSWORD=mypassword \
-e POSTGRES_DB=mydb \
-p 5432:5432 \
-d postgres:16
# データの永続化
docker run --name postgres-db \
-e POSTGRES_PASSWORD=mypassword \
-v postgres_data:/var/lib/postgresql/data \
-p 5432:5432 \
-d postgres:16
基本設定
postgresql.conf
# 接続設定
listen_addresses = '*'
port = 5432
max_connections = 100
# メモリ設定
shared_buffers = 256MB
effective_cache_size = 1GB
work_mem = 4MB
maintenance_work_mem = 64MB
# WAL設定
wal_buffers = 16MB
checkpoint_completion_target = 0.9
max_wal_size = 1GB
min_wal_size = 80MB
# ログ設定
logging_collector = on
log_directory = 'log'
log_filename = 'postgresql-%Y-%m-%d_%H%M%S.log'
log_statement = 'all'
log_duration = on
log_min_duration_statement = 1000ms
pg_hba.conf
# TYPE DATABASE USER ADDRESS METHOD
# 本ローカル接続
local all postgres peer
local all all md5
# IPv4 LAN接続
host all all 192.168.1.0/24 md5
# SSL接続
hostssl all all 0.0.0.0/0 md5
# レプリケーション
host replication replicator 192.168.1.0/24 md5
基本操作
データベース管理
-- データベース作成
CREATE DATABASE myapp
WITH ENCODING 'UTF8'
LC_COLLATE 'ja_JP.UTF-8'
LC_CTYPE 'ja_JP.UTF-8'
TEMPLATE template0;
-- ユーザー作成
CREATE USER appuser WITH PASSWORD 'secure_password';
GRANT CONNECT ON DATABASE myapp TO appuser;
GRANT USAGE ON SCHEMA public TO appuser;
GRANT CREATE ON SCHEMA public TO appuser;
-- テーブル作成
CREATE TABLE users (
id SERIAL PRIMARY KEY,
username VARCHAR(50) UNIQUE NOT NULL,
email VARCHAR(255) NOT NULL,
profile JSONB,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
-- インデックス作成
CREATE INDEX idx_users_email ON users(email);
CREATE INDEX idx_users_profile_gin ON users USING GIN(profile);
JSON操作
-- JSON/JSONBデータの操作
INSERT INTO users (username, email, profile) VALUES
('john_doe', '[email protected]', '{"age": 30, "city": "Tokyo", "skills": ["Python", "SQL"]}');
-- JSON検索
SELECT * FROM users WHERE profile->>'city' = 'Tokyo';
SELECT * FROM users WHERE profile->'skills' ? 'Python';
SELECT * FROM users WHERE profile @> '{"age": 30}';
-- JSON集約
SELECT
profile->>'city' as city,
COUNT(*) as user_count,
jsonb_agg(username) as usernames
FROM users
GROUP BY profile->>'city';
パフォーマンス最適化
インデックス戦略
-- B-treeインデックス(デフォルト)
CREATE INDEX idx_users_username ON users(username);
-- 部分インデックス
CREATE INDEX idx_active_users ON users(username) WHERE active = true;
-- 複合インデックス
CREATE INDEX idx_users_city_age ON users((profile->>'city'), (profile->>'age')::int);
-- GINインデックス(JSON、配列、フルテキスト)
CREATE INDEX idx_users_profile ON users USING GIN(profile);
-- GiSTインデックス(地理空間、範囲)
CREATE INDEX idx_location ON locations USING GIST(geom);
クエリ最適化
-- EXPLAIN ANALYZEによる実行計画確認
EXPLAIN (ANALYZE, BUFFERS, FORMAT JSON)
SELECT * FROM users WHERE profile->>'city' = 'Tokyo';
-- 統計情報の更新
ANALYZE users;
-- バキューム(領域回収)
VACUUM ANALYZE users;
-- 自動バキューム設定
ALTER TABLE users SET (
autovacuum_vacuum_scale_factor = 0.1,
autovacuum_analyze_scale_factor = 0.05
);
レプリケーション設定
マスター設定
# postgresql.conf
wal_level = replica
max_wal_senders = 10
max_replication_slots = 10
synchronous_commit = on
-- レプリケーションユーザー作成
CREATE USER replicator REPLICATION LOGIN CONNECTION LIMIT 10 ENCRYPTED PASSWORD 'replica_password';
スレーブ設定
# ベースバックアップ作成
pg_basebackup -h master_host -D /var/lib/postgresql/16/main -U replicator -P -W
# スタンバイ設定
echo "standby_mode = 'on'" >> /var/lib/postgresql/16/main/recovery.conf
echo "primary_conninfo = 'host=master_host port=5432 user=replicator password=replica_password'" >> /var/lib/postgresql/16/main/recovery.conf
バックアップ戦略
論理バックアップ
# pg_dump(単一データベース)
pg_dump -h localhost -U postgres -d myapp -f myapp_backup.sql
# pg_dumpall(全データベース)
pg_dumpall -h localhost -U postgres -f all_databases_backup.sql
# カスタム形式(圧縮、並列復元可能)
pg_dump -h localhost -U postgres -d myapp -Fc -f myapp_backup.dump
# 復元
pg_restore -h localhost -U postgres -d myapp -v myapp_backup.dump
物理バックアップ
# pg_basebackup
pg_basebackup -h localhost -D /backup/base -U postgres -P -W
# WALアーカイブ設定
# postgresql.conf
archive_mode = on
archive_command = 'cp %p /backup/wal/%f'
# Point-in-Time Recovery (PITR)
pg_ctl stop -D /var/lib/postgresql/16/main
rm -rf /var/lib/postgresql/16/main/*
tar -xzf /backup/base_backup.tar.gz -C /var/lib/postgresql/16/main
echo "restore_command = 'cp /backup/wal/%f %p'" > /var/lib/postgresql/16/main/recovery.conf
echo "recovery_target_time = '2024-01-15 14:30:00'" >> /var/lib/postgresql/16/main/recovery.conf
pg_ctl start -D /var/lib/postgresql/16/main
監視とメンテナンス
基本監視クエリ
-- 接続状況確認
SELECT
datname,
usename,
client_addr,
state,
query_start,
query
FROM pg_stat_activity
WHERE state != 'idle';
-- テーブルサイズ確認
SELECT
schemaname,
tablename,
pg_size_pretty(pg_total_relation_size(schemaname||'.'||tablename)) as size
FROM pg_tables
ORDER BY pg_total_relation_size(schemaname||'.'||tablename) DESC;
-- インデックス使用状況
SELECT
schemaname,
tablename,
indexname,
idx_scan,
idx_tup_read,
idx_tup_fetch
FROM pg_stat_user_indexes
ORDER BY idx_scan DESC;
パフォーマンス統計
-- スロークエリ確認(pg_stat_statementsが必要)
SELECT
query,
calls,
total_time,
mean_time,
rows
FROM pg_stat_statements
ORDER BY total_time DESC
LIMIT 10;
-- ロック状況確認
SELECT
l.locktype,
l.database,
l.relation,
l.page,
l.tuple,
l.virtualxid,
l.transactionid,
l.classid,
l.objid,
l.objsubid,
l.virtualtransaction,
l.pid,
l.mode,
l.granted,
a.usename,
a.query
FROM pg_locks l
LEFT JOIN pg_stat_activity a ON l.pid = a.pid
WHERE NOT l.granted;
高度な機能
パーティショニング
-- レンジパーティション
CREATE TABLE sales (
id SERIAL,
sale_date DATE NOT NULL,
amount DECIMAL(10,2)
) PARTITION BY RANGE (sale_date);
-- パーティション作成
CREATE TABLE sales_2024_q1 PARTITION OF sales
FOR VALUES FROM ('2024-01-01') TO ('2024-04-01');
CREATE TABLE sales_2024_q2 PARTITION OF sales
FOR VALUES FROM ('2024-04-01') TO ('2024-07-01');
-- ハッシュパーティション
CREATE TABLE user_data (
user_id INTEGER,
data TEXT
) PARTITION BY HASH (user_id);
CREATE TABLE user_data_0 PARTITION OF user_data
FOR VALUES WITH (modulus 4, remainder 0);
フルテキスト検索
-- tsvector型でのフルテキスト検索設定
ALTER TABLE articles ADD COLUMN search_vector tsvector;
UPDATE articles SET search_vector =
to_tsvector('japanese', title || ' ' || content);
CREATE INDEX idx_articles_search ON articles USING GIN(search_vector);
-- 検索実行
SELECT title, ts_rank(search_vector, query) as rank
FROM articles, to_tsquery('japanese', 'PostgreSQL & データベース') query
WHERE search_vector @@ query
ORDER BY rank DESC;
PostgreSQLは、その豊富な機能セット、高い拡張性、堅牢性により、小規模なWebアプリケーションから大規模エンタープライズシステムまで幅広く利用されています。オープンソースでありながらエンタープライズグレードの機能を提供し、継続的な開発により常に最新の技術トレンドに対応しています。