『遅い・壊れる・直せない』SQL に共通する15パターン
SQL の事故の多くは典型パターンの繰り返しです。本記事では編集部の視点で、実務で頻出するアンチパターンと対策を公開情報をもとに整理します。SQL チューニング もご参考に。
設計フェーズの5つの罠
(1) EAV (Entity-Attribute-Value):可変属性をテーブルで表現→ JOIN 地獄。(2) カンマ区切り値:1カラムに複数値→検索不能。(3) Polymorphic Association:参照先テーブルを動的に→ FK 不可。(4) マルチカラム属性:phone1/phone2/phone3 等→拡張困難。(5) 正規化不足:データ重複・更新異常。対策は、(1)JSONB併用、(2)関連テーブル分離、(3)テーブル統合、(4)正規化、(5)1NF〜3NF適用、です。
キー・ID 設計の5つの罠
(1) natural key の濫用:メールアドレスを主キーに→変更不可。(2) connectionless ID 採番:分散環境で衝突。(3) auto increment 多用:本番値推測可能、移行困難。(4) UUID v4 の偏在:B-tree インデックス効率悪化。(5) ID 漏洩:URL に整数ID で全件取得可能。対策は、(1)surrogate key、(2)ULID/UUIDv7、(3)範囲予約、(4)ULIDで時系列性、(5)スラッグ化、です。
クエリの5つの罠
(1) SELECT *:転送量爆発。(2) N+1 問題:ループ内クエリ。(3) OR 多用:インデックス効きにくい。(4) 関数を WHERE に:インデックス無効化。(5) 暗黙的型変換:意図せず全表スキャン。対策は、(1)必要列のみ、(2)JOIN/IN化、(3)UNION ALL、(4)関数インデックス、(5)型整合、です。
運用面の罠
(1) マイグレーション直接 ALTER:本番ダウンタイム。(2) VACUUM 未実行:テーブル膨張。(3) バックアップだけリストア未確認。(4) 本番DB の直接接続:誤操作リスク。(5) スロークエリ放置:時限爆弾。対策は、(1)Online Schema Change、(2)autovacuum 調整、(3)定期リストア訓練、(4)Bastion+pg_admin、(5)定期棚卸し、です。バックアップ&DR もご参考に。
NULL の扱い
(1) NULL = NULL は偽:IS NULL を使う。(2) 集約関数の挙動:COUNT(col) は NULL を除外。(3) JOIN での NULL:LEFT JOIN の右側で発生。(4) NULL 許容の濫用:意味不明な状態に。(5) NOT NULL DEFAULTを活用。NULL の意味を統一すると保守性が大きく上がります。
失敗しがちなパターン
(1) ORM 任せで生成 SQL を見ない。(2) EXPLAIN を読まない。(3) テーブル設計を後で直そうとする。(4) 本番のみで実行される SQL を見落とし。(5) レビューを技術リーダーに集中:知識が伝播しない。対策は、(1)ログでSQL確認、(2)EXPLAIN 必須レビュー、(3)初期設計に時間、(4)pg_stat_statements、(5)勉強会、です。