リレーショナルデータベース(エンジン非依存)
概要
リレーショナルデータベースのためのエンジンに依存しないベストプラクティス。原則とパターンは一度記述され、SQLの方言が異なる箇所(MSSQL vs MySQL/MariaDB)のみがインラインでフラグ付けされるか、方言早見表にまとめられています。正しさと、実測された証拠に基づく最小限の変更を最適化します。
使用するタイミング
- スキーマの設計またはレビュー(テーブル、キー、正規化、データ型)。
- インデックスの追加または修正、低速クエリやフルテーブルスキャンの診断。
- 実行計画を読み解き、ボトルネックを見つける。
- トランザクション分離、ロック、デッドロックの選択またはトラブルシューティング。
- 大規模な結果セットのページネーション。N+1アクセスの排除。
- 本番環境で安全なスキーママイグレーションの計画。
対象外: エンジン内部の深掘り(InnoDBバッファプールなどのストレージエンジン内部、ベンダー固有機能、T-SQLのみの構文、レプリケーション/シャーディングトポロジ)。エンジン固有のドキュメント、または専用のシングルエンジンスキルを使用してください。
ワークフロー
- 最初にコンテキストを確立する。 どのエンジン+メジャーバージョンか? 読み取り/書き込みの比率、行数、レイテンシ目標、OLTPか分析か。これらの要素によってアドバイスが変わります。
- 各セクションでリンクされている関連リファレンスのみを読む。
- 問題を解決する最小の変更を、トレードオフとともに提案する。
- 証拠で検証する — 実行計画と行/タイミングのメトリクスを変更前後で取得する(
references/execution-plans.mdを参照)。経験則だけで判断しない。 - 本番環境の場合、ロールバック計画とデプロイ後の検証を含める。
スキーマ設計
- リレーションシップを明示的にモデル化し、正規化(3NF/BCNF)から始め、計測された理由がある場合のみ非正規化する。すべてのテーブルには安定したプライマリキーが必要です。
- 正しいデータ型の中で最も狭いものを選択し、不正な状態をアプリケーションコードだけでなくスキーマレベル(NOT NULL、UNIQUE、CHECK、FK)で制約する。
インデックス作成
WHERE、JOIN、ORDER BYで使用されるカラムにインデックスを作成する。推測ではなく選択性に基づいて。複合インデックスの順序: 等価条件のカラムを最初に、次に範囲/ソート(左端プレフィックスルール)。範囲述語は、それ以降のカラムに対するインデックスの使用を停止します。- カバリングインデックスはテーブルルックアップを回避します。未使用/重複したインデックスを監査して削除する。すべてのインデックスは書き込みを遅くします。
クエリ最適化
- 述語をSARG可能に保つ —
WHERE内のインデックス付きカラムに関数や暗黙的なキャストを使用しない。必要なカラムのみを選択する。重複除去が不要な場合はUNIONよりもUNION ALLを、大きな書き込みはバッチ処理を優先する。 - 大きな
OFFSETの代わりにキーセット(カーソル)ページネーションを使用する。N+1をバッチ処理または結合で排除する。
リファレンス: クエリ最適化 · 実行計画 · ページネーション
トランザクションとロック
- トランザクションは短く保つ。I/Oや低速な処理はトランザクションの外で行う。デッドロックを避けるために一貫した順序で行にアクセスする。デッドロックを想定し、バックオフ付きでリトライする。
- 自分のエンジンのデフォルト分離レベル(エンジンによって異なる)と、各レベルで許容される異常を把握する。ロック読み取り(
FOR UPDATE)は習慣ではなく、意図的に使用する。
リファレンス: トランザクションと分離 · ロックとデッドロック
マイグレーションとDDL
- スキーマ変更は追加ベースで後方互換性を保つ。拡張 → バックフィル → 縮小。大規模な/ロックを伴うDDLにはオンライン戦略とロールバックパスが必要です。
リファレンス: マイグレーションとDDL
エンジン方言の違い
オートインクリメント、識別子の引用、ページネーション、Upsert、文字列関数、現在時刻、EXPLAIN、分離レベルのデフォルトはすべてエンジン間で異なります。ポータブルなSQLを書く前に、ターゲットエンジンの構文を確認してください。
リファレンス: エンジン方言早見表
ガードレール
- 経験則ではなく、実測された証拠(実行計画、メトリクス)を優先する。
- 動作がエンジンに依存する場合は、エンジンとメジャーバージョンを明記する。
- 破壊的な操作(DROP/DELETE/TRUNCATE または元に戻せないマイグレーション)の前に、明示的な人間の承認を得る。常にバックアップが存在することを確認する。