アプリケーションエンジニアからDB絡みの相談を受けるたび、同じような誤解を繰り返し目にしてきました。その中でも特に効果の大きいポイントだけを厳選して紹介しています。

実行計画の見方

アプリ開発者向けTips図

図1: パフォーマンスに影響する4つの開発Tips

EXPLAIN PLAN FOR
SELECT o.id, c.name
  FROM orders o
  JOIN customers c ON o.cust_id = c.id
 WHERE o.status = 'OPEN';

------------------------------------------
| Id | Operation              | Cost |
------------------------------------------
|  0 | SELECT STATEMENT       |  120 |
|  1 |  HASH JOIN             |  120 |
|  2 |   TABLE ACCESS FULL    |   80 |
|  3 |   INDEX RANGE SCAN     |   20 |
------------------------------------------

読むときの観点

  1. ネストは下から上へ実行される
  2. FULL SCAN は意図したものか?
  3. INDEX RANGE / UNIQUE / SKIP の別
  4. JOIN は NESTED / HASH / MERGE の別
  5. SORT (Disk) / WINDOW (Buffer)
  6. RowsとCostの見積りが現実と乖離していないか(統計の鮮度を疑う)

ロックと待機事象

同時実行制御のためにDBは様々なロックを取りますが、設計を誤ると待機やデッドロックの原因になります。

デッドロック対策の鉄則: 「常に同じ順序でロックを取る」。テーブルの更新順序をコーディング規約で決める。

よくある落とし穴

  • コミットを忘れる: 長時間トランザクションがUNDO/ロックを圧迫し、他セッションを巻き込む。
  • 1行ずつ処理(Loop): Round Tripが爆発。SET演算で一発処理を検討。
  • 全件取得 → アプリ側filter: ネットワーク帯域・メモリを浪費。WHEREはDBに任せる。
  • バインド変数を使わない: 毎回ハードパース。Shared Pool競合・実行計画ぶれの原因。
  • SELECT *: 不要列の転送・INDEX Only Scanの機会損失。
  • TRUNCATEとDELETE混同: TRUNCATEはDDL ⇒ コミット不可・トリガ非発火。
  • NULL比較に「=」を使う: = NULL は常に偽。IS NULL を使う。
  • JOIN結果の重複: 意図しない多対多が発生。DISTINCTで隠さず原因を直す。

SQLレビューチェックリスト

コードレビューの場でSQLを見る際、見落としやすい観点を一覧にした。実行計画の確認と合わせて使うと効果的。

チェック観点確認内容問題が起きる理由
バインド変数の使用 リテラル値が埋め込まれていないか 毎回ハードパース → 共有プール圧迫 → 同時実行数が多いシステムで顕著
WHERE句の絞り込み順序 高選択度の条件が先に来ているか。関数で列を加工していないか 列に関数をかける(TO_DATE(col)など)とインデックスが使われない
JOIN件数の見積もり 多対多のJOINで結果件数が爆発しないか 外部キーが想定通りでない場合、Cartesian Productに近い結果になる
SELECT列の指定 SELECT * を使っていないか 不要列の転送コスト・Covering Index(Index Only Scan)の機会損失
NULLの扱い = NULL でなく IS NULL を使っているか = NULLは常にFALSEを返すため、意図した行が1件も取れない

💡 実行計画と一緒に使う
EXPLAIN PLANで全件スキャン(FULL)が出たら即修正ではなく、まずテーブルサイズと取得件数を確認する。小テーブルや大量取得ならフルスキャンが最適な場合もある。

まとめ

シリーズ全体のまとめです。

  1. DBは「メモリで処理し、ログで永続化する」
  2. Optimizerは統計を元にコスト最小の計画を選ぶ
  3. INDEXは読み取りを高速化し、書込コストを払う
  4. REDOがコミットの本体。DBの永続性はここに依存
  5. Temporary Spaceは「メモリで足りない時の溢れ先」
  6. DB Linkは便利だが、ネット越し・分散COMMITの罠あり
  7. 設定は「メモリ・ファイル配置・ログ多重化・監査」
実行計画を読める開発者は、DBの中で何が起きているかを語れるようになる。

参考リソース

  • 公式ドキュメント: Oracle Database Concepts / PostgreSQL Documentation / SQL Server Architecture / IBM Db2 Knowledge Center
  • 古典の名著: 「データベース実践入門」「SQLパフォーマンス詳解」「Use The Index, Luke!」
  • 実行計画の読み方: EXPLAIN PLAN (Oracle) / EXPLAIN ANALYZE (Postgres) / SET STATISTICS PROFILE (SQL Server)
  • パフォーマンス分析: AWR / Statspack (Oracle) / pg_stat_statements (PG) / Query Store (SQL Server)