データベースのパフォーマンス問題は、SES現場でエンジニアが最も頻繁に遭遇する課題の一つです。「あのクエリが遅い」「インデックスをどう張ればいいかわからない」「本番環境のスロークエリが増えてきた」——こうした問題にOpenAI Codex CLIが強力な解決策を提供します。
OpenAI Codex CLIはコードベース全体を理解した上でSQLの最適化提案やインデックス設計を行えるため、データベースの専門知識がなくても効果的なチューニングが可能です。
この記事では、Codex CLIを使ったデータベース最適化の実践テクニックを、基礎から応用まで体系的に解説します。

なぜCodex CLIがデータベース最適化に効果的なのか
アプリケーションコードとSQLの両方を理解
Codex CLIの最大の強みは、アプリケーションコードとSQLの両方を横断的に分析できることです。
従来のDB最適化ツール(pgTune、MySQLTunerなど)は、データベース側の設定やクエリ単体しか分析できません。しかしCodex CLIは以下のような横断分析が可能です。
- ORMコードからSQLを推測: ActiveRecordやSQLAlchemyのコードから実際に発行されるSQLを分析
- N+1クエリの検出: ループ内でのDB呼び出しパターンを自動検出
- マイグレーション履歴との整合性: 既存のインデックスとクエリのミスマッチを発見
# アプリケーション全体のDB関連コードを分析
codex "このプロジェクトのデータベースアクセスパターンを分析して、
パフォーマンスボトルネックになりそうな箇所を特定して。
ORM経由のクエリもSQLに展開して分析して。"
Codex CLIの分析能力
| 分析対象 | 従来ツール | Codex CLI |
|---|---|---|
| SQLクエリ単体 | ✅ EXPLAIN ANALYZE | ✅ EXPLAIN + 改善提案 |
| インデックス設計 | ⚠️ 手動分析 | ✅ アクセスパターンから自動提案 |
| N+1クエリ | ❌ 検出不可 | ✅ コードレベルで検出 |
| ORMコードの最適化 | ❌ 対象外 | ✅ eager loading提案 |
| スキーマ設計 | ⚠️ 手動レビュー | ✅ クエリパターンから最適化提案 |
| マイグレーション生成 | ❌ 手動作成 | ✅ 変更DDLを自動生成 |
環境構築
前提条件
# Codex CLIの確認
codex --version
# データベースクライアント
psql --version # PostgreSQL
mysql --version # MySQL
# スロークエリログの有効化(PostgreSQLの場合)
# postgresql.conf
# log_min_duration_statement = 100 # 100ms以上をログ出力
# shared_preload_libraries = 'pg_stat_statements'
プロジェクト設定
# AGENTS.md
## データベース最適化ルール
- PostgreSQL 16 を使用
- ORM: Prisma (TypeScript) / SQLAlchemy (Python)
- クエリ実行時間の目標: 単純クエリ < 10ms, 複雑クエリ < 100ms
- インデックスは使用率を確認してから追加
- 本番データベースへの直接操作は禁止(マイグレーション経由)
- EXPLAIN ANALYZE の結果を添えて最適化提案する
基本操作:スロークエリの分析と最適化
スロークエリの特定
# PostgreSQLのスロークエリログを分析
codex "以下のスロークエリログを分析して、最も影響の大きいクエリTOP5を特定して。
各クエリについて、遅い原因と改善案を提示して。
$(cat /var/log/postgresql/slow-query.log | tail -1000)"
EXPLAIN ANALYZEの解析
# 特定のクエリのEXPLAIN結果をCodex CLIに解析させる
codex "以下のEXPLAIN ANALYZE結果を分析して、
ボトルネックと改善策を日本語で説明して。
$(psql -d mydb -c "EXPLAIN (ANALYZE, BUFFERS, FORMAT JSON)
SELECT u.name, COUNT(o.id) as order_count, SUM(o.total_amount) as total
FROM users u
JOIN orders o ON u.id = o.user_id
WHERE o.created_at >= '2026-01-01'
GROUP BY u.id, u.name
ORDER BY total DESC
LIMIT 100;")"
Codex CLIは以下のような詳細な分析を提供します。
## 分析結果
### ボトルネック
1. **Seq Scan on orders**: ordersテーブルのシーケンシャルスキャン(全件走査)
- 推定コスト: 45,000
- 実行時間: 2.3秒
2. **Hash Join**: ハッシュ結合のメモリ使用量が work_mem を超過
- ディスクスピル発生 → パフォーマンス低下
### 改善策
1. **複合インデックスの追加**:
```sql
CREATE INDEX idx_orders_created_user ON orders (created_at, user_id)
INCLUDE (total_amount);
- work_memの一時的な増加:
SET work_mem = '256MB';
- パーティショニングの検討(レコード数が100万件超の場合)
### SQLクエリの書き換え
```bash
codex "以下のSQLクエリを最適化して。実行計画の改善も含めて。
SELECT *
FROM products p
WHERE p.category_id IN (
SELECT c.id FROM categories c WHERE c.parent_id = 5
)
AND p.price > 1000
AND p.status = 'active'
ORDER BY p.created_at DESC
LIMIT 20;"
Codex CLIは以下の改善を提案します。
-- 最適化後
SELECT p.id, p.name, p.price, p.created_at
FROM products p
INNER JOIN categories c ON p.category_id = c.id
WHERE c.parent_id = 5
AND p.price > 1000
AND p.status = 'active'
ORDER BY p.created_at DESC
LIMIT 20;
-- 推奨インデックス
CREATE INDEX idx_products_status_price_created
ON products (status, price, created_at DESC)
WHERE status = 'active';
CREATE INDEX idx_categories_parent ON categories (parent_id);
インデックス設計の自動化
アクセスパターン分析
codex "このプロジェクトの全SQLクエリ(ORMコード含む)を分析して、
最適なインデックス設計を提案して。以下の形式で出力して:
1. 各テーブルの推奨インデックス
2. 既存インデックスで不要なもの
3. 複合インデックスのカラム順序の理由
4. 部分インデックスが有効なケース
5. マイグレーションSQL"
インデックス使用状況の分析
# PostgreSQLのインデックス使用統計を取得
psql -d mydb -c "
SELECT
schemaname,
tablename,
indexname,
idx_scan as index_scans,
idx_tup_read,
idx_tup_fetch,
pg_size_pretty(pg_relation_size(indexrelid)) as index_size
FROM pg_stat_user_indexes
ORDER BY idx_scan ASC
LIMIT 20;" > /tmp/index_stats.txt
codex "以下のインデックス統計を分析して、
未使用のインデックス(削除候補)と
不足しているインデックスを特定して。
$(cat /tmp/index_stats.txt)"
複合インデックスの設計原則
Codex CLIは以下の原則に基づいてインデックスを提案します。
codex "usersテーブルへの以下のクエリパターンに対して、
最適な複合インデックスを設計して。カラム順序の理由も説明して。
1. WHERE status = 'active' AND created_at > '2026-01-01' ORDER BY name
2. WHERE email = '[email protected]'
3. WHERE company_id = 123 AND role = 'engineer' ORDER BY created_at DESC
4. WHERE name LIKE '田中%' AND status = 'active'"
Codex CLIの提案例:
-- クエリ1用:等値条件 → 範囲条件 → ソート条件の順
CREATE INDEX idx_users_status_created_name
ON users (status, created_at, name)
WHERE status = 'active';
-- クエリ2用:ユニーク性の高いカラム単独
CREATE UNIQUE INDEX idx_users_email ON users (email);
-- クエリ3用:等値条件2つ → ソート条件
CREATE INDEX idx_users_company_role_created
ON users (company_id, role, created_at DESC);
-- クエリ4用:GINインデックス(前方一致検索)
-- PostgreSQLではtext_pattern_opsを使用
CREATE INDEX idx_users_name_pattern
ON users (name text_pattern_ops)
WHERE status = 'active';
N+1クエリの検出と修正
ORMコードの分析
codex "このプロジェクトのORMコードを分析して、
N+1クエリが発生している箇所を特定して。
各箇所について修正コードも生成して。
特に以下のパターンに注意して:
1. ループ内でのリレーション参照
2. シリアライザーでのネストされた関連
3. テンプレート内でのlazy loading"
Prismaの場合
// ❌ N+1クエリ(Codex CLIが検出)
const users = await prisma.user.findMany();
for (const user of users) {
const orders = await prisma.order.findMany({
where: { userId: user.id }
});
// orders を使った処理
}
// ✅ Codex CLIの修正提案
const users = await prisma.user.findMany({
include: {
orders: {
where: { status: 'completed' },
orderBy: { createdAt: 'desc' },
take: 10,
}
}
});
SQLAlchemyの場合
# ❌ N+1クエリ(Codex CLIが検出)
users = session.query(User).filter(User.status == 'active').all()
for user in users:
print(user.orders) # lazy loading → N+1
# ✅ Codex CLIの修正提案
from sqlalchemy.orm import joinedload
users = (
session.query(User)
.filter(User.status == 'active')
.options(joinedload(User.orders))
.all()
)
パフォーマンスモニタリングの自動化
pg_stat_statements分析
codex "pg_stat_statementsの上位クエリを分析して、
チューニング優先度をつけて改善案を出して。
$(psql -d mydb -c "
SELECT
query,
calls,
total_exec_time / 1000 as total_seconds,
mean_exec_time as avg_ms,
rows,
shared_blks_hit,
shared_blks_read
FROM pg_stat_statements
ORDER BY total_exec_time DESC
LIMIT 20;
")"
定期的なDB健康診断スクリプト
codex "PostgreSQLの定期健康診断スクリプトを生成して。以下の項目を含めて:
1. テーブルサイズとブロート率
2. インデックス使用率
3. キャッシュヒット率
4. デッドタプル率(VACUUM必要度)
5. ロングトランザクション
6. コネクション数
出力はJSON形式で、閾値超過時にアラートを出して。"
生成されるスクリプト例:
#!/bin/bash
# db-health-check.sh
DB_NAME="${1:-mydb}"
OUTPUT="/tmp/db-health-$(date +%Y%m%d).json"
echo "データベース健康診断: $DB_NAME"
echo "================================="
# キャッシュヒット率
CACHE_HIT=$(psql -d "$DB_NAME" -t -c "
SELECT round(
sum(heap_blks_hit) / nullif(sum(heap_blks_hit) + sum(heap_blks_read), 0) * 100, 2
) as cache_hit_ratio
FROM pg_statio_user_tables;")
echo "キャッシュヒット率: ${CACHE_HIT}%"
if (( $(echo "$CACHE_HIT < 95" | bc -l) )); then
echo "⚠️ キャッシュヒット率が95%未満。shared_buffersの増加を検討"
fi
# テーブルブロート
echo ""
echo "テーブルブロート:"
psql -d "$DB_NAME" -c "
SELECT
schemaname || '.' || relname as table,
n_dead_tup,
n_live_tup,
round(n_dead_tup::numeric / nullif(n_live_tup, 0) * 100, 2) as dead_ratio,
last_autovacuum
FROM pg_stat_user_tables
WHERE n_dead_tup > 1000
ORDER BY n_dead_tup DESC
LIMIT 10;"
# ロングトランザクション
echo ""
echo "ロングトランザクション(5分超):"
psql -d "$DB_NAME" -c "
SELECT
pid,
now() - xact_start as duration,
state,
left(query, 100) as query
FROM pg_stat_activity
WHERE xact_start < now() - interval '5 minutes'
AND state != 'idle'
ORDER BY xact_start;"
マイグレーション生成の自動化
スキーマ変更の安全な実行
codex "usersテーブルにphone_numberカラムを追加する
安全なマイグレーションを生成して。以下の条件で:
- ダウンタイムゼロ
- ロールバック可能
- NOT NULL制約は後から追加
- バリデーション付き"
Codex CLIが生成するマイグレーション:
-- Migration: add_phone_number_to_users
-- Safe deploy strategy: 3-step migration
-- Step 1: カラム追加(NULLable、ロック最小)
ALTER TABLE users ADD COLUMN phone_number VARCHAR(20);
-- Step 2: バックフィル(バッチ処理で負荷分散)
-- アプリケーションコードで段階的に実行
UPDATE users SET phone_number = ''
WHERE phone_number IS NULL
AND id BETWEEN 1 AND 10000;
-- Step 3: 制約追加(全データが埋まった後)
ALTER TABLE users
ADD CONSTRAINT users_phone_number_check
CHECK (phone_number IS NOT NULL)
NOT VALID;
-- バリデーション(ロック時間短い)
ALTER TABLE users VALIDATE CONSTRAINT users_phone_number_check;
-- ロールバック
-- ALTER TABLE users DROP COLUMN phone_number;
SES現場での実践パターン
パターン1:参画初日のDB分析
# プロジェクトに参画した初日にDB全体を分析
codex "このプロジェクトのデータベースを総合分析して。
以下のレポートを作成して:
1. ER図(Mermaid記法)
2. テーブルサイズランキング
3. リレーション構造
4. 潜在的なパフォーマンス問題
5. インデックスの過不足"
パターン2:障害時の緊急対応
# 本番DBが遅くなった時の緊急分析
codex "以下のpg_stat_activity結果から、
DBが遅くなっている原因を特定して、
即座に実行可能な対処法を教えて。
ロック競合やデッドロックの可能性も確認して。
$(psql -d proddb -c "SELECT * FROM pg_stat_activity WHERE state = 'active';")"
パターン3:大規模テーブルのパーティショニング
codex "ordersテーブル(5億レコード)のパーティショニング設計をして。
以下の条件で:
- クエリパターン: 日付範囲検索が80%
- 保持期間: 3年
- 月次パーティション
- 既存データの移行手順も含めて
- ダウンタイム最小化"
ベストプラクティスまとめ
DB最適化チェックリスト
# Codex CLIでチェックリストを一括実行
codex "以下のDB最適化チェックリストを実行して、
各項目のステータスと改善アクションを一覧で出して。
□ スロークエリ(100ms超)の特定と最適化
□ 未使用インデックスの削除
□ 不足インデックスの追加
□ N+1クエリの排除
□ キャッシュヒット率 > 99%
□ テーブルブロート < 20%
□ コネクションプール設定の最適化
□ VACUUM/ANALYZEの実行状況
□ ロングトランザクションの排除
□ クエリプランの安定性確認"
パフォーマンス目標値
| メトリクス | 目標値 | 警告値 |
|---|---|---|
| 平均クエリ時間 | < 10ms | > 50ms |
| P99クエリ時間 | < 100ms | > 500ms |
| キャッシュヒット率 | > 99% | < 95% |
| コネクション使用率 | < 70% | > 85% |
| デッドタプル率 | < 10% | > 20% |
| インデックスヒット率 | > 99% | < 95% |
まとめ
OpenAI Codex CLIを活用したデータベース最適化は、SES現場で即戦力となるスキルです。特に以下のポイントを意識して活用してください。
- アプリケーションコードとSQLの両方を分析させる:N+1クエリやORM最適化はコードレベルの分析が必須
- EXPLAIN ANALYZEの結果をCodex CLIに渡す:実行計画の解釈と改善提案を自動化
- インデックス設計はアクセスパターンから:既存クエリを全量分析してから設計
- マイグレーションは安全に:ダウンタイムゼロ・ロールバック可能な方法で
- 定期的な健康診断を自動化:問題が顕在化する前に予防
まずはプロジェクトのスロークエリログをCodex CLIに分析させるところから始めてみましょう。