DB設計したいNight #4 そーだいさんと失敗から学びながらDB設計したいnightに行ってきました。
所感
今回はパネルディスカッション形式でパネラーの失敗事例を題材にトークする感じ。事例を見てすぐに解決策を説明されてて、培ってきた経験とノウハウが圧倒的だなと感じました。短い時間でしたが、学びや刺激がありました。
今回のディスカッションで話していたことは書籍の内容がベースになっているものが多かったです。DB設計は奥が深いっす。まだ読み途中なので引き続き勉強しよう。
失敗から学ぶRDBの正しい歩き方 (Software Design plus)
以下、メモから抜粋。
桁、桁数、フォーマットが想定と違うケース。
- アプリケーションに合わせたデータとマッピングするテーブルを用意する
- トリッキーな手段で対応せず基本に忠実に
- 実際のデータがどうなっているかは意識すること
共通項目が多いが部分的に異なる。STI (継承関係を1テーブルで表すこと) を採用したケース。
- アプリとDBの親子関係は一致させる必要はない
- 親子関係を逆転させる (共通テーブルを子にする)
- typeごとにVIEWを用意する
- PostgreSQLの継承を使う
- 最初に小さく作る
- あとからくっつけるのは簡単
- 最初から大きく作るとあとから分けるのは大変
#DBSekkeiNight pic.twitter.com/DlgyU9JwAx
— kaiba@技術書典 う32C (@kaiba) May 16, 2019
- 共通テーブルのIDと親テーブルのIDx2を持つ関連テーブル
- 親テーブルのIDの排他を担保するためにCHECK制約を使う
- パフォーマンスなどのトレードオフを考えること
- 親テーブルのIDの排他を担保するためにCHECK制約を使う
- 共通テーブルのIDを親テーブルが持つ
- 共通テーブルにフラグを持たせがち
- 1つのテーブルに複数のステータスや状態を持たせない
- 複数のステータスを条件にする場合は別テーブルに分ける
- その共通項目は本当に共通なのかをよく考える
なんでも一発で取れるVIEWを用意したが、JOINが多すぎてパフォーマンスがわるい。画面などの用途ごとにVIEWを用意したが、VIEWの数が多くなり、VIEW同士のJOINやVIEW間の依存が煩雑になったケース。カラム追加でどこに影響があるか特定するのが困難に。
- キャッシュ、マテビュー、サマリーテーブル
- 更新頻度の少ないデータはjsonにしてS3に置いてDBアクセスを減らしたり
- VIEWからVIEWを作る、2階層のキャッシュはNG
- 古いキャッシュが残らないように
- リフレッシュの順序を考慮する必要があったり
- 最初にしっかり論理設計をしてから物理設計をする
- VIEWやマテビューを使うときは、設計にミスがありそれをRDBの機能でカバーするということ
- 可能であれば設計を見直す方がよい
#DBSekkeiNight pic.twitter.com/7i4A5mCoIU
— kaiba@技術書典 う32C (@kaiba) May 16, 2019
- VIEWを使うケース
- リファクタリング時に互換性を保ちたいとき (テーブル分割など)
- セキュリティ上、見せたくないカラムを隠蔽したいとき
- 誤って
select * ...
してセキュアなデータが露出しないように
- 誤って
- 事前に(複数の)フラグを解決したVIEWを用意したいとき
- アプリ側で条件を書くと複雑になるため
不要になったカラムは消すか?残すか?
- 確実に消していいことがわかるなら消す
- アプリ側で抽象化してあると変更しやすい
- 算出すればわかるデータはアプリ側で算出する (年齢⇛生年月日から算出)
- カラムやテーブルに
OLD
などのプレフィックスを付ける- 将来削除されることがわかるようにコメントを残す
- Oracleではメタデータで設定できる
- クエリや実行計画、indexに使われなくなる
ログテーブル