myzk.dev
Books
SQL アンチパターン
下記は自分用のメモです。
本の引用がほとんどのためパスワードを設定してます。
見る
Table of Content
I部 データベース論理設計のアンチパターン
1章 ジェイウォーク(信号無視)
1.1 目的:複数の値を持つ属性を格納する
1.2 アンチパターン:カンマ区切りフォーマットのリストを格納する
1.2.1 特定のアカウントに関連する製品の検索
1.2.2 特定の製品に関連するアカウントの検索
1.2.3 集約クエリの作成
1.2.4 特定の製品に関連するアカウントの更新
1.2.5 製品 IDの妥当性検証
1.2.6 区切り文字の選択
1.2.7 リストの長さの制限
1.3 アンチパターンの見つけ方
1.4 アンチパターンを用いてもよい場合
1.5 解決策:交差テーブルを作成する
1.5.1 特定のアカウントに関連する製品の検索/特定の製品に関連するアカウントの検索
1.5.2 集約クエリの作成
1.5.3 製品の連絡先の更新
1.5.4 製品 IDの妥当性検証
1.5.5 区切り文字の選択
1.5.6 リストの長さの制限
1.5.7 交差テーブルの他のメリット
2章 ナイーブツリー(素朴な木)
2.1 目的:階層構造を格納し、クエリを実行する
2.2 アンチパターン:常に親のみに依存する
2.2.1 隣接リストへのクエリ実行
2.2.2 隣接リストのツリーのメンテナンス
2.3 アンチパターンの見つけ方
2.4 アンチパターンを用いてもよい場合
2.5 解決策:代替ツリーモデルを使用する
2.5.1 経路列挙( Path Enumeration)
2.5.2 入れ子集合( Nested Set)
2.5.3 閉包テーブル( Closure Table)
2.5.4 どの設計を使うべきか
3章 IDリクワイアド(とりあえずID)
3.1 目的:主キーの規約を確立する
3.2 アンチパターン:すべてのテーブルに「 id」列を用いる
3.2.1 冗長なキーが作成されてしまう
3.2.2 重複行を許可してしまう
3.2.3 キーの意味がわかりにくくなる
3.2.4 USINGを使用する
3.2.5 複合キーは使いにくい
3.3 アンチパターンの見つけ方
3.4 アンチパターンを用いてもよい場合
3.5 解決策:状況に応じて適切に調整する
3.5.1 わかりやすい列名にしよう
3.5.2 規約に縛られない
3.5.3 自然キーと複合キーの活用
4章 キーレスエントリ(外部キー嫌い)
4.1 目的:データベースのアーキテクチャを単純化する
4.2 アンチパターン:外部キー制約を使用しない
4.2.1 完ぺきなコードを前提にしている
4.2.2 ミスを調べなければならない
4.2.3 「私のミスではありません!」
4.2.4 「キャッチ =22」な UPDATE
4.3 アンチパターンの見つけ方
4.4 アンチパターンを用いてもよい場合
4.5 解決策:外部キー制約を宣言する
4.5.1 複数テーブルの変更をサポートする
4.5.2 オーバーヘッド、 ……にはなりません
5章 EAV(エンティティ・アトリビュート・バリュー)
5.1 目的:可変属性をサポートする
5.2 アンチパターン:汎用的な属性テーブルを使用する
5.2.1 属性を取得するにはどうするか
5.2.2 データ整合性をどう保つか
5.2.3 行を再構築しなければならない
5.3 アンチパターンの見つけ方
5.4 アンチパターンを用いてもよい場合
5.5 解決策:サブタイプのモデリングを行う
5.5.1 シングルテーブル継承
5.5.2 具象テーブル継承
5.5.3 クラステーブル継承
5.5.4 半構造化データ
5.5.5 後処理
6章 ポリモーフィック関連
6.1 目的:複数の親テーブルを参照する
6.2 アンチパターン:二重目的の外部キーを使用する
6.2.1 ポリモーフィック関連を定義する
6.2.2 ポリモーフィック関連へのクエリ実行
6.2.3 非オブジェクト指向の例
6.3 アンチパターンの見つけ方
6.4 アンチパターンを用いてもよい場合
6.4.1 ポリモーフィック関連を意識的に選択するとき
6.5 解決策:関連(リレーションシップ)を単純化する
6.5.1 参照を逆にする
6.5.2 交差テーブルの作成
6.5.3 交差点に交通信号を設置する
6.5.4 両方の「道」を見る
6.5.5 「道」を合流させる
6.5.6 共通の親テーブルの作成
7章 マルチカラムアトリビュート(複数列属性)
7.1 目的:複数の値を持つ属性を格納する
7.2 アンチパターン:複数の列を定義する
7.2.1 値の検索
7.2.2 値の追加と削除
7.2.3 一意性の保証
7.2.4 増加する値の処理
7.3 アンチパターンの見つけ方
7.4 アンチパターンを用いてもよい場合
7.5 解決策:従属テーブルを作成する
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部 データベース物理設計のアンチパターン
9章 ラウンディングエラー(丸め誤差)
9.1 目的:整数の代わりに小数値を使用する
9.2 アンチパターン: FLOATデータ型を使用する
9.2.1 丸めが避けられない
9.2.2 SQLでの FLOATの使用
9.3 アンチパターンの見つけ方
9.4 アンチパターンを用いてもよい場合
9.5 解決策: NUMERICデータ型を使用する
10章 サーティワンフレーバー(31のフレーバー)
10.1 目的:列を特定の値に限定する
10.2 アンチパターン:限定する値を列定義で指定する
10.2.1 中身は何だろう
10.2.2 新しいフレーバーの追加
10.2.3 昔ながらの味は色褪せない
10.2.4 移植が困難
10.3 アンチパターンの見つけ方
10.4 アンチパターンを用いてもよい場合
10.5 解決策:限定する値をデータで指定する
10.5.1 値セットの取得
10.5.2 参照テーブルの値の更新
10.5.3 廃止された値のサポート
10.5.4 移植が容易
11章 ファントムファイル(幻のファイル)
11.1 目的:画像をはじめとする大容量メディアファイルを格納する
11.2 アンチパターン:物理ファイルの使用を必須と思い込む
11.2.1 ファイルの削除時における問題
11.2.2 トランザクション分離の問題
11.2.3 ロールバック時における問題
11.2.4 データベースのバックアップツール使用時における問題
11.2.5 SQLアクセス権限使用時における問題
11.2.6 ファイルは SQLデータ型ではない
11.3 アンチパターンの見つけ方
11.4 アンチパターンを用いてもよい場合
11.4.1 常に 2つの設計を検討する
11.5 解決策:必要に応じて BLOB型を採用する
12章 インデックスショットガン(闇雲インデックス)
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)
13.1 目的:欠けている値を区別する
13.2 アンチパターン: NULLを一般値として使う、または一般値を NULLとして使う
13.2.1 式で NULLを扱う
13.2.2 NULLを許容する列の検索
13.2.3 プリペアドステートメントで NULLを扱う
13.2.4 NULLの使用を避ける
13.3 アンチパターンの見つけ方
13.4 アンチパターンを用いてもよい場合
13.5 解決策: NULLを一意な値として使う
13.5.1 スカラー式での NULL
13.5.2 論理式での NULL
13.5.3 NULLの検索
13.5.4 列に NOT NULL制約を宣言する
13.5.5 動的なデフォルト
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章 プアマンズ・サーチエンジン(貧者のサーチエンジン)
16.1 目的:全文検索を行う
16.2 アンチパターン:パターンマッチ述語を使用する
16.3 アンチパターンの見つけ方
16.4 アンチパターンを用いてもよい場合
16.5 解決策:適切なツールを使用する
16.5.1 ベンダー拡張
16.5.2 MySQLのフルテキストインデックス
16.5.3 Oracleでのテキストインデックス
16.5.4 Microsoft SQL Ser verでの全文検索
16.5.5 PostgreSQLでのテキスト検索
16.5.6 SQLiteでの全文検索( FTS)
16.5.7 サードパーティーのサーチエンジン
17章 スパゲッティクエリ
17.1 目的:SQLクエリの数を減らす
17.2 アンチパターン:複雑な問題をワンステップで解決しようとする
17.2.1 意図に反した結果
17.2.2 さらなる弊害
17.3 アンチパターンの見つけ方
17.4 アンチパターンを用いてもよい場合
17.5 解決策:分割統治を行う
17.5.1 ワンステップずつ
17.5.2 UNIONを用いる
17.5.3 CASE式と SUM関数を組み合わせる
17.5.4 上司の問題を解決する
17.5.5 SQLを用いた SQLの自動的な記述
18章 インプリシットカラム(暗黙の列)
18.1 目的:タイプ数を減らす
18.2 アンチパターン:ショートカットの罠に陥る
18.2.1 リファクタリングにおける問題
18.2.2 隠れた代償
18.2.3 求めなければ得られない
18.3 アンチパターンの見つけ方
18.4 アンチパターンを用いてもよい場合
18.5 解決策:列名を明示的に指定する
18.5.1 誤りの防止
18.5.2 それは多分、必要ない(YAGNI:You Ain't Gonna Need It)
18.5.3 ワイルドカードを使えない局面はいずれ訪れる
IV部 アプリケーション開発のアンチパターン
19章 リーダブルパスワード(読み取り可能パスワード)
19.1 目的:パスワードのリカバリーとリセットを行う
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章 SQLインジェクション
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章 マジックビーンズ(魔法の豆)
24.1 目的: MVCの M(モデル)を単純化する
24.2 アンチパターン:モデルがアクティブレコードそのもの
24.2.1 アクティブレコードはモデルをデータベーススキーマに強く依存させてしまう
24.2.2 アクティブレコードは CRUD機能を公開してしまう
24.2.3 アクティブレコードはドメインモデル貧血症をもたらす
24.2.4 マジックビーンズのユニットテストは困難
24.3 アンチパターンの見つけ方
24.4 アンチパターンを用いてもよい場合
24.5 解決策:モデルがアクティブレコードを「持つ」ようにする
24.5.1 モデルを理解する
24.5.2 ドメインモデルの使用
24.5.3 プレーンなオブジェクトのテスト
24.5.4 現実的に考える
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 運用ポリシーの策定
© 2023 myzk.dev