よくある当たり前っぽい内容ですが、はてなに入る前はあまりやったことがなかったので勉強しながらやっていました(解析器の結果をapiで見せるみたいなことが多かったので、DBそもそもほとんど使っていなかった…)。最近はデータ移行職人業務をやっている。
前提
前提があったほうが説明が書きやすい。is_hoge
のようなbooleanなフィールドがhoge
、fuga
、piyo
のようにenumな値を取るように変更が必要という前提で話を進めます。
作戦: 下の層から丁寧にやっていく
一気にやると大変なことになるので、下の層からちびちび進めていきましょう。Pull Requestを送るときに↓のようなやることリストを付けておくと、全体のどの辺をやっているか分かりやすくなるのでレビュアーにやさしい感じになりそうですね。
- [model層]
hoge
、fuga
、piyo
を表わすようなフィールドを追加 - [DB層]
hoge
、fuga
、piyo
を表わすようなフィールドを追加 - [model層]
is_hoge
に破壊的な操作(作成/更新/削除)をするときに、hoge
、fuga
、piyo
を表わすカラムにも変更を反映 - [DB層]
is_hoge
カラムの状態からhoge
、fuga
、piyo
を表わすカラムの残りを埋める- 例:
is_hoge
がtrueだったらhoge
、falseだったらfuga
みたいなSQLを発行したり
- 例:
- [model層]
is_hoge
ではなくhoge
、fuga
、piyo
カラムのみで値を返すようにするis_hoge
カラムには書き込まれなくなる
- [DB層]
is_hoge
カラムをdropする - [controller層]必要だったら
hoge
、fuga
、piyo
の状態を返す、設定するエンドポイントを生やす - [controller層]
is_hoge
を返すようなAPIがあるようだったらhoge
、fuga
、piyo
フィールドも追加して返すようにする - [frontend層]APIで
is_hoge
を見ている箇所を追加されたhoge
、fuga
、piyo
フィールドを見て処理するように変更 - [controller層]不要だったら
is_hoge
を返すようなAPIは消す
基本的には
- 最初は両方に書く
- ロジックを新しいほうを使うようにする
- 使わなくなった箇所を消す
というのを隣接する層毎にやっていくとスムーズでした。
知ってる && 試すといいやつ
CASE式
is_hoge
カラムに値によってhoge_fuga_type
カラムの値を埋める、みたいなSQLを発行したいとき。boolなので、UPDATEを二回発行してもいいけど、CASE式を使うと一回で書けるのでよい。
UPDATE target_table SET hoge_fuga_type = CASE is_hoge WHEN true THEN 0 -- hoge WHEN false THEN 1 -- fuga END ;
ALTER TABLEにかかる時間を計測
ALTER TABLEに予想しないくらい時間がかかって、サービスに影響が出るというのは避けたいので、backupサーバー等で時間をはかっておくと安心です。トランザクションを貼って、ROLLBACKすれば大丈夫。
hoge_fuga_service=> BEGIN; BEGIN hoge_fuga_service=> \timing Timing is on. hoge_fuga_service=> ALTER TABLE "target_table" ADD COLUMN "hoge_fuga_type" INT NOT NULL DEFAULT 1; ALTER TABLE Time: 82.552 ms hoge_fuga_service=> ALTER TABLE "target_table" DROP COLUMN "hoge_fuga__type"; ALTER TABLE Time: 7.523 ms hoge_fuga_service=> ROLLBACK;
- 作者: ミック
- 出版社/メーカー: 翔泳社
- 発売日: 2013/08/07
- メディア: Kindle版
- この商品を含むブログ (4件) を見る