■ 1. データベースリファクタリングの重要性
- 基本認識: データベースの寿命はアプリケーションよりも長く、不適切なデータベースがコードやサービスの成長を止めるため、サービスの健康を保ち成長するためにはデータベースのリファクタリングが必要である
- データベース設計の特性: データベース設計は積み木のようにちゃんと検討された仕様追加を正しく積み上げていけるが、マジカルな設計をすると仕様変更が出来なくなり、次の仕様追加がどうにも出来ない状態になる
- 一度作ったデータベースは消せないため、定期的なメンテナンスは必須であり、問題は小さいうちに直さないとDBの肥大化と共に問題も大きくなる
■ 2. データベースの不吉な臭い
- RDBアンチパターン:データベースの迷宮、失われた事実、やりすぎたJOIN、効かないindex、フラグの闇などがあり、破綻した値(delete_flagが1、2、0、9、99、NULLなど複数存在する状態)などが典型例である
- 不吉な臭いの具体例: 複数の目的に使われるカラム(レコードの属性に合わせて値の意味が変わる)、複数の目的に使われるテーブル(テーブルバージョンなど)、冗長なデータ(非正規化の末のデータ整合性の破綻)、カラムの多すぎるテーブル(memo1、memo2、memo3など)、行の多すぎるテーブル、「スマート」カラム(論理IDなどデータの中の情報によって意味が変わる)、変更の恐怖(データベースの変更やデータの更新によってアプリケーションが壊れるのでは?となり手を付けれない状態)がある
- 技術的負債の判断: チーズなのか腐った牛乳なのか、本当に改修が必要かどうかを見極める必要があり、腐った牛乳はサービスの生死に関わるため継続的なデータベース・リファクタリングが必要である
■ 3. データベース・リファクタリングの分類
- 6つの分類:
- 構造(テーブルやViewの定義)
- データ品質(データの値)
- 参照整合性(テーブルの関連性)
- メソッド(ストアドプロシジャ)
- 変更(テーブルやカラムの追加)
- アーキテクチャ(アプリとのインターフェイス)
- システムの性質: シングルアプリケーション(1つのアプリケーションが1つのデータベースを扱う)の時はDBマイグレーションが活き、コードでDBを管理できる強さがあるが、マルチアプリケーション(複数のアプリケーションが1つのデータベースを扱う)の時は依存関係の多さが課題となる
■ 4. プロセスとリファクタリング戦略
- データベースの特徴: データは常に変化しており、影響範囲が広く、DBを止めることが難しいため、データベースリファクタリングはすごく長いスパンになる
- 戦うための準備:
- 抽象化: 永続化フレームワークを導入する
- モニタリング: 変化の影響をリアルタイムに知るためにモニタリングして状態を知る
- 品質を担保する: 影響が広いからこそテストを書き、シナリオテストも大切で、関連するアプリケーションの全てが対象となる
- 覚悟: サービス停止の壁を政治と技術の両方で解決する必要があり、レプリケーションなどを使って限りなく0に近づけるが完全に0には出来ないので政治力が問われる
- 実施の判断: 手間も時間もかかるため、リファクタリングの意味はあるか、作業に応じた効果はあるか、今やるべきか、を検討することが大事である
- 実施手順: 対象を選定し移行期間を決め、テストとモニタリングを揃え、リリース戦略を決める必要があり、複数のアプリケーションの変更が必要な場合に全てのアプリケーションが動く必要があり、同時にアプリケーションが更新できない場合もあるので移行期間が必要である
- 移行期間の設計: 移行中は前状態でも新状態でもアプリケーションは動く必要があり、DBの機能(例えばトリガー)をうまく活用して、旧アプリと新アプリの両方が動作するように設計する
■ 5. 現場での実践ポイント
- リファクタリング手法: DBマイグレーションツールを使う、DBの機能を利用する、手動でSQLを実行するという選択肢がある
- リファクタリングのコツ: 移行前に戻せること、移行中は過去の状態を保持すること(backupやレプリケーションを使う)、小さな変更を長いスパンで繰り返すこと(DBは影響範囲が広いので切り分けをしやすくすることが大事)、兎にも角にもテストとモニタリングが大事である
- 綺麗なリファクタリング: 参照と更新の読み込み先を分ける、更新のボトルネックを分ける、データ設計を見直す、適切にINDEXを活用する
- 闇の深いリファクタリング: JOINを非正規化で補う、外部キー制約を外す、とりあえずキャッシュに突っ込む、極度のスケールアップなどは避けるべきである
- コミュニティの活用: DBの機能をうまく活用し、postgresql-jp SlackやMySQL-casual Slackなどのデータベースコミュニティを積極的に利用する
■ 6. まとめ
- 継続的改善の必要性: データベースの死はサービスの死であり、解決できる人は英雄であるため、サービスやチームを守るためにそのために学ぶ必要がある
- 学習の重要性: 愚者は経験に学び、賢者は過去に学ぶため、周囲の経験談から学び積極的にコミュニティを利用し、RDBの知識は寿命が長く覚えれば仕事で長い間役に立つ
- 実行の重要性: 今日から改善するのはあなた自身であり、手を動かした人だけが世界を変える