RDBには様々なアンチパターンがある。
「失敗から学ぶRDBの正しい歩き方」は、初級者が陥りがちなRDBのアンチパターンを紹介し、それぞれの対処法を紹介している。
このエントリでは、「失敗から学ぶRDBの正しい歩き方」の内容をまとめる。
データベースの寿命は、一般的にアプリケーションよりも長いため、技術的負債が積もると改修しづらくなる。
早めのリファクタリングを心がけよう。
履歴は更新ではなく追加し、最新レコードを有効レコードとしたり、削除処理も削除を表すレコードのINSERTとして保存したりして履歴(事実)が失われるのを防ぐ。
usersテーブルにおいて、年齢カラムを使って30代のみを抽出するクエリがあり、30代のユーザは全体の10%なのでインデックスが効く。
一方、20代のユーザは50%を占めている。10年後、急にインデックスが効かなくなるということが起こる。*1
「IDが9から始まるユーザは管理者」というように、意味を持たせたIDは「スマートカラム」と呼ばれるアンチパターンである。
データには本来の意味以外の情報を持たせてはならない。*2
バックアップは正しく戻せるところまでがバックアップだ。
「バックアップを取っていたと思ったら中身はエラーログだった」なんてことにならないように、普段からシステム障害を想定した訓練をしておこう。
RDBMSごとに異なるロックの振る舞いを正しく理解しておこう。
トランザクション分離レベルと、RDBMSごとにデフォルトの設定が異なることを理解しておこう。*3
Amazon RDSなどのフルマネージドサービスを利用することで「自分たちでコンフィグを管理しない」という選択肢があることも頭に入れておこう。
delete_flag
が delete_falg
という名前で作られてしまった。
- 正しい名前のカラム
delete_flag
を追加する - INSERTやUPDATEに対してトリガーを定義し、typoしたカラムと正しいカラムを同じデータにする
- アプリケーション側で新しいカラムを参照するように変更する
- 動作に問題がなければトリガーとtypoしたカラムをDROPする
次のようなことに気をつける。
払い戻しなどの取り消し処理に対応できるか配送状況などステータス変化を追えるかトラブル対応時、欲しい情報が失われていないか
RDBに履歴を持たせない場合、次のような方法もある。
遅延レプリケーションを使う *4
アプリケーションログとしてElasticsearchなどの分析ツールに保存する
-
id: 1, 属性名: 年齢, 値: 30
-
id: 2, 属性名: 職業, 値: CRE
といったように、複数の目的に使われるカラムを持つ設計は「EAV」と呼ばれるアンチパターンである。
必須属性が指定できない、データ型が指定できないなど、様々な弊害を引き起こす。
-
id: 1, 名前: おとよ, 住所: 東京都…, 参照先: User
-
id: 2, 名前: ミクシィ, 住所: 東京都渋谷区…, 参照先: Company
といったように、レコードによって参照する親テーブルが変わる設計は「Polymorphic Associations」と呼ばれるアンチパターンにあたる。
外部キー制約が使えない、データを取り出すまでJOINする対象がわからないといった問題がある。
RDBMSのテーブルとアプリケーションのクラスが1:1になる構造は「マジックビーンズ」と呼ばれるアンチパターンであり、下記のような問題を引き起こす。
CRUD機能を公開することでビジネスロジックのModelとは別の場所から呼ばれることがあるController層やService層にビジネスロジックが記載された「ドメインモデル貧血症」をもたらすデータベースにアクセスする場所が散在し、ビジネスロジックがデータに依存するため、ユニットテストが難しくなる
PHP製のフレームワークSymfonyでは、Modelを、データのCRUDだけを担うリポジトリクラス、サービスが必要なデータを取り出し加工するデータクラス、ビジネスロジックを担うサービスクラスの3層に分けうまく抽象化している。
以上、このエントリでは、「失敗から学ぶRDBの正しい歩き方」の内容をまとめた。
- インデックスを利用するためには、(1)検索結果がテーブル全体の20%未満、(2)検索対象のテーブルが十分大きい、という条件が必要
- 例えば「新たに○○なユーザを追加して」と言われたとき困る
- PostgreSQLのデフォルトはRead Committedで、MySQLのデフォルトはRepeatable Read
- 気付くのが遅れるなどして遅延時間を超えると事実が失われてしまうので注意
コメントを送る
コメントはブログオーナーのみ閲覧できます