まとめ
-
DBリファクタリングは必須
- DB設計の問題は技術的負債
- 負債は雪だるま式に増える
-
計画的に
-
移行期間を設けるなど
- 整合性の確保にトリガーが大変役に立つ
-
-
参考図書: データベース・リファクタリング
-
守備範囲
- どのようなリファクタリングがあるか
-
守備範囲外
- どのようなDB設計にすべきか
- リファクタリングによってどのような改善を行うべきか
-
リファクタリング
- DBリファクタリング: 1つ以上のテーブルの設計を変更する
- 定義変更自体はALTERコマンド一撃
-
現実、そんなに簡単な話ではない
-
アプリケーションはリリース済、運用中
- テーブルにデータ格納済
- テーブルアクセス依存の処理がある
-
DBのリファクタリングは大変
-
影響範囲甚大
- クエリの書き換え
- 各種制約の確認
- ビューの修正
- トリガーの修正
- ストアドプロシージャの修正
マルチアプリケーションにおけるDB環境
- 共通のDBを複数のアプリケーションから参照するのはよくあること
なぜリファクタリングが必要なのか
- アプリケーションが変化する以上、本質的に必要
-
しかし大変なので「やらない理由」を探して放置しがち
- 負債は貯まるばかり
- 負債を返済するにはリファクタリングするほかない
リファクタリングの手順
-
アプリケーションへの影響を抑えつつ、アプリケーションのペースに合わせた移行をするための手順
- 作業前後のバックアップ
-
スキーマの変更
- 移行のための過渡的なスキーマ
- データの移行
- アプリケーション移行のためのトリガーの作成
- アプリケーションのデプロイ
- 移行のためのトリガーの削除
- 移行のためのカラムの削除
スキーマの移行期間
- 移行期間を設けるケース
- 古いロジックのアプリケーションが一定期間残る
- そのため、元のスキーマと変更後のスキーマが共存する必要がある
反復的なリファクタリング
- アプリケーションは反復的にリファクタリングするのにDBスキーマは変更しない過ち
- 反復的な開発は効率が良いため、技術的負債も効率良く溜まってしまう
- DBのリファクタリングも反復的に行え
回帰テスト
-
十分なテストケースが存在していることが前提
- アプリケーションの機能が損われたらリファクタリングではない、破壊しているだけ
- 機能が損われていないことを確認する方法はテストしかない
ベンチマークテスト
- リファクタリングの結果、パフォーマンスが著しく低下するケースは珍しくない
- パフォーマンスが低下していないことを確認する方法はベンチマークテストしかない
-
本番に忠実な環境を用意すること
-
H/W
- パブリッククラウドのおかげで敷居下がった
- OS
- テストデータの規模
-
マイグレーション利用のススメ
-
スキーマのバージョン管理
- RoRのActive Recordで導入されたしくみ
- 【補】Laravelでもおなじみ
- 制限: バージョン分岐ができない
- 戻す場合のロジックもテストすること
-
バックアップじゃダメなの?
- ダメ
- データも巻き戻ってしまう
トリガーを使って2つのテーブル間で同期を取る
-
移行期間中、新旧テーブルのデータの整合性を確保するために使う
- 循環に注意
- 移行が完了したらトリガーを削除する
- トリガーのテストも忘れずに
リファクタリングの種類
- よりよいDB設計とは
- どのようなリファクタリングで改善できるのか
インデックスの追加・削除
-
軽微
- クエリ書き換え生じない
-
テーブルが持つ論理的な意味が変更されうることに注意
- 主キーやユニークインデックスによる一意性制約の導入/削除
- ベンチマークテストで性能劣化のなきことを確認せよ
カラム名の変更
-
過渡
- 異なる名前で同じデータを持ったカラムを2つ持たせる
-
行単位のトリガーで同期
- MySQLなどの製品でサポート
NOT NULL制約の導入
-
1NFにするために後からでもNOT NULLをつけることは大切
- あるいはリレーション分割
-
NOT NULLをつけるにあたり、既存のデータにNULLが含まれていたら若干の調整が必要
- NULLだった個所の値がデフォルト値でもNULLでも動くようにクエリを書き換える
主キーの定義変更
-
変更が必要になるケース
- 主キーが既約ではない場合
- 主キーから別のカラムへの関数従属性がなくなってしまった
- サロゲートキーからナチュラルキーへの変更、あるいはその逆
無損失分解
-
移行期間が必要な場合は面倒
- 元のテーブルを残しつつ新しいテーブルを作成
-
双方のテーブルでデータの同期
- トリガー
- カスケード
テーブルの垂直分割と統合
-
複数のテーブルで直交性が満たされていない場合、テーブルの統合が必要
- 【補】 マスタの名寄せ的な
コラム: 関連テーブルの実態
- 1:N -> M:N
-
2段階のリファクタリングのショートカットと考えられる
- 主キーを変更して行持ち
- 第2正規化
リファクタリングのためのベストプラクティス
- リファクタリングに強い
- リファクタリングがあまり必要にならない
正規化と直交性
カラムではなくテーブルを追加する
-
カラムを追加する前に熟考せよ:
- カラムの初期値はあるか
- 主キーに対して関数従属しているか
- これらを満たすならカラムを追加して問題ない
-
テーブルを追加するというアプローチも
-
メリット
- 既存のテーブルを変更しなくてよい
-
デメリット
-
JOIN増える
- 内部表に対して主キーでアクセスできる実行計画ならば、パフォーマンスペナルティは存外小さい
-
-
SELECT * を使わない
-
1NF崩れる
- 順序を持ち込むことにほかならないため
アプリケーションを疎結合に
-
データへアクセスするロジックを共通化する
- アプリケーション側の修正個所が少なくなるよう
-
例
- DAO: Data Access Object
- 【補】 Table Data Gatewayとか