『SQLアンチパターン』
https://gyazo.com/532c77d1d6035f0e88b8f9c299c6a541
2013/1/26
原著
最近改訂版(?)が出たらしい
タイトルが意味不明すぎない?「Volume 1」ってなんだよmrsekut.icon
2022/11
内容はそんなに変わってない模様
感想
DB、SQLの基礎を知っていれば誰でも読めるレベルの内容
例示が具体的で親切
各章は独立しているのでどこからでも読める
パターンによっては、「こんなアホな設計、逆に思いつかんわ」というのもある
軽く読んで、パターンを知ってリンクを付けて、実際に起きそうになった時に熟読すれば良さそうmrsekut.icon
アンチパターンの命名(章名)は、分かりづらいので微妙ではという気はする
この本が有名なのでググればヒットするが、初見者には直感的ではない
タイトルはSQLだが、以下らへんについて書かれている
論理設計
物理設計
SQL
サンプルデータベース
I部 データベース論理設計のアンチパターン
1章 ジェイウォーク(信号無視)
0から設計するならこんなことしないけど、途中で仕様が変わったらありえなくもないのかmrsekut.icon
3章 IDリクワイアド(とりあえずID)
主張がふわふわしてる章だなmrsekut.icon
あらゆるtableにサロゲートキーであるidを付けるというアンチパターン
4章 キーレスエントリ(外部キー嫌い)
外部キー制約を使わないことに対する指摘
普通の外部キー制約の話
5章 EAV(エンティティ・アトリビュート・バリュー)
特にgroupbyで計算する時に
同じcolumnにないといけない
比較可能なフォーマットになってないといけない
というのもある
解決策が微妙なものが多いな
それを解決策と呼ぶべきじゃないでしょ、という感じのが多い
6章 ポリモーフィック関連
7章 マルチカラムアトリビュート(複数列属性)
「1つの投稿に、複数のタグを付けられる」のような仕様の時にどうtableを作るか
tag1,tag2,tag3のように上限を決め打ちしてcolumnを作るというアンチパターン
ここにきて急に基本的すぎるmrsekut.icon
8章 メタデータトリブル(メタデータ大増殖)
8.1 目的:スケーラビリティを高める
8.2 アンチパターン:テーブルや列をコピーする
8.2.1 テーブルの増殖
8.2.2 データの整合性を管理する
8.2.3 データの同期
8.2.4 一意性の保証
8.2.5 テーブルをまたいだクエリ実行
8.2.6 メタデータの同期
8.2.7 参照整合性の管理
8.2.8 メタデータトリブル列の特定
8.3 アンチパターンの見つけ方
8.4 アンチパターンを用いてもよい場合
8.5 解決策:パーティショニングと正規化を行う
8.5.1 水平パーティショニングの使用
8.5.2 垂直パーティショニングの使用
8.5.3 従属テーブルの導入
II部 データベース物理設計のアンチパターン
FLOAT型を使うと誤差が生じるので注意する
where hourly_rate = 59.95のように書いた時に、
DB内に保存されている値が、59.950000762939のようになっていると、当然一致しない
where abs(hourly_rate - 59.95) < 0.000001のように書くらしい
SUM関数で集約した時に誤差が出るなど
どうするか?
精度とスケールを指定できる
11章 ファントムファイル(幻のファイル)
画像をDBで管理する際に、
画像本体はS3などの外部サービスに入れて、
そのURLをDBに入れる
というのが一般的だが、著者はこれをアンチパターンと呼んでる
著者自身も、この主張が少数派であることは認識してるっぽい
これ、当然だと思いすぎてメリデメを考えたこともなかったなmrsekut.icon
やることはないにしても知っておいて損はなさそう
初学者がこの章読むと真に受けそうだなmrsekut.icon
12.1 目的:パフォーマンスを最適化する
12.2 アンチパターン:闇雲にインデックスを使用する
12.2.1 インデックスをまったく定義しない
12.2.2 インデックスを多く定義し過ぎる
12.2.3 インデックスが役立たないとき
12.3 アンチパターンの見つけ方
12.4 アンチパターンを用いてもよい場合
12.5 解決策:「MENTOR」の原則に基づいて効果的なインデックス管理を行う
12.5.1 Measure(測定)
12.5.2 Explain(解析)
12.5.3 Nominate(指名)
12.5.4 Test(テスト)
12.5.5 Optimize(最適化)
12.5.6 Rebuild(再構築)
III部 クエリのアンチパターン
13章 フィア・オブ・ジ・アンノウン (恐怖のunknown)
NULLの使用は避けるべきだが、かといって-1とか9999のような初期値を用意するのもおかしい
解決策の章、解決策の話ししてなくない?
NULLの説明をしてるだけ
この章微妙だなmrsekut.icon
14章 アンビギュアスグループ (曖昧なグループ)
14.1 目的:グループ内で最大値を持つ行を取得する
14.2 アンチパターン:非グループ化列を参照する
14.2.1 単一値の原則( Single-Value Rule)
14.2.2 SQLがクエリの意図を汲んでくれるとは限らない
14.3 アンチパターンの見つけ方
14.4 アンチパターンを用いてもよい場合
14.5 解決策:曖昧でない列を使用する
14.5.1 関数従属性のある列のみにクエリを実行する
14.5.2 相関サブクエリを使用する
14.5.3 導出テーブルを使用する
14.5.4 JOINを使用する
14.5.5 他の列に対しても集約関数を使用する
14.5.6 グループごとにすべての値を連結する
15章 ランダムセレクション
15.1 目的:サンプル行をフェッチする
15.2 アンチパターン:データをランダムにソートする
15.3 アンチパターンの見つけ方
15.4 アンチパターンを用いてもよい場合
15.5 解決策:特定の順番に依存しない
15.5.1 1と最大値の間のランダムなキー値を選択する
15.5.2 欠番の穴の後にあるキー値を選択する
15.5.3 すべてのキー値のリストを受けとり、ランダムに 1つを選択する
15.5.4 オフセットを用いてランダムに行を選択する
15.5.5 ベンダー依存の解決策
16章 プアマンズ・サーチエンジン (貧者のサーチエンジン)
ベンダー拡張
MySQL, Oracle, Microsoft SQL Server, PostgreSQL, SQLiteそれぞれの解説
一度検索したことのあるクエリをキャッシュする感じのtableをもう1個作る
17章 スパゲッティクエリ
複雑な処理を、1つのSQLで書こうとする、というアンチパターン
デカルト積になるのは、単にJOINの仕方がおかしいからでは?mrsekut.icon
クエリが大きいことと直接は関係なくない?
なんか例が極端だなmrsekut.icon
「レポート」を例にしてるのも逃げてる感じがある
1回きりのレポートを出したいだけならパフォーマンスはほぼ問題にならない
パフォーマンスが問題になるのはアプリケーションでの話であって、それを例に持ってくるべき
18章 インプリシットカラム (暗黙の列)
「タイプ数を減らすため」という目的で、ワイルドカード*を使わない
型がちゃんとしたORMを使ってたら大丈夫mrsekut.icon
IV部 アプリケーション開発のアンチパターン
19章 リーダブルパスワード (読み取り可能パスワード)
19.2 アンチパターン:パスワードを平文で格納する
19.2.1 パスワードの格納
19.2.2 パスワードの認証
19.2.3 パスワードを電子メールで送信する
19.3 アンチパターンの見つけ方
19.4 アンチパターンを用いてもよい場合
19.5 解決策:ソルトを付けてパスワードハッシュを格納する
19.5.1 ハッシュ関数を理解する
19.5.2 SQLでのハッシュの使用
19.5.3 ハッシュにソルトを加える
19.5.4 SQLからパスワードを隠す
19.5.5 パスワードをリカバリーするのではなく、リセットする
20.1 目的:動的 SQLを記述する
20.2 アンチパターン:未検証の入力をコードとして実行する
20.2.1 アクシデントは起きる
20.2.2 ウェブ最大のセキュリティ脅威
20.2.3 対処法の追求
20.3 アンチパターンの見つけ方
20.4 アンチパターンを用いてもよい場合
20.5 解決策:誰も信用してはならない
20.5.1 入力のフィルタリング
20.5.2 動的値のパラメータ化
20.5.3 動的値を引用符で囲む
20.5.4 ユーザーの入力をコードから隔離する
20.5.5 他の開発者にコードをレビューしてもらう
21章 シュードキー・ニートフリーク(疑似キー潔癖症)
21.1 目的:欠番を詰める
21.2 アンチパターン:隙間を埋める
21.2.1 欠番を割り当てる
21.2.2 既存行に番号を振り直す
21.2.3 データ不一致の元
21.3 アンチパターンの見つけ方
21.4 アンチパターンを用いてもよい場合
21.5 解決策:疑似キーの欠番は埋めない
21.5.1 行のナンバリング
21.5.2 GUIDの使用
21.5.3 最も重要な問題
22章 シー・ノー・エビル(臭いものに蓋)
22.1 目的:簡潔なコードを書く
22.2 アンチパターン:肝心な部分を見逃す
22.2.1 診断せずに判断する
22.2.2 見逃しがちなコード
22.3 アンチパターンの見つけ方
22.4 アンチパターンを用いてもよい場合
22.5 解決策:エラーから優雅に回復する
22.5.1 リズムを維持する
22.5.2 ステップをたどり直す
23章 ディプロマティック・イミュニティ(外交特権)
23.1 目的:ベストプラクティスを採用する
23.2 アンチパターン: SQLを特別扱いする
23.3 アンチパターンの見つけ方
23.4 アンチパターンを用いてもよい場合
23.5 解決策:包括的に品質問題に取り組む
23.5.1 文書化
23.5.2 バージョン管理
23.5.3 テスティング
23.5.4 複数のブランチを扱う
24章 マジックビーンズ (魔法の豆)
MVCとActive Recordの話題はあまり興味がないのでほぼ読んでないmrsekut.icon
25章 砂の城
25.1 目的:サービスの安定稼働
25.2 アンチパターン:想定不足
25.3 アンチパターンの見つけ方
25.4 アンチパターンを用いてもよい場合
25.5 解決策
25.5.1 ベンチマーク
25.5.2 テスト環境の構築
25.5.3 例外処理
25.5.4 バックアップ
25.5.5 高可用性
25.5.6 ディザスタリカバリ
25.5.7 運用ポリシーの策定
V部 付録
付録A 正規化のルール
A.1 リレーショナルとは何か
A.1.1 行に上下の順番がない
A.1.2 列に左右の順番がない
A.1.3 重複行を許可しない
A.1.4 すべての列は 1つの型を持ち、各行に 1つの値を持つ
A.1.5 行に隠されたコンポーネントがない
A.2 正規化の神話
A.3 正規化とは何か
A.3.1 第 1正規形
A.3.2 第 2正規形
A.3.3 第 3正規形
A.3.4 ボイスコッド正規形
A.3.5 第 4正規形
A.3.6 第 5正規形
A.3.7 他の正規形
A.4 正規化は常識的なもの
付録B 参考文献
索引