LoginSignup
36
28

More than 5 years have passed since last update.

サービスを止めずにRailsで大きなテーブルにalter tableを実行する

Last updated at Posted at 2016-04-07

サービスが成長してテーブルが肥大化してくるとインデックスの追加などを気軽に行うことができなくなってきます。alter tableするためにメンテナンスの時間を取ることもできますが、無停止で変更できるならそれに越したことはありません。

この記事では、Railsで開発されているWebサービスでそういったことを実現するための方法を紹介します。

tl;dr

  • Railsのmigrationを使うのではなく、無停止で alter table するための専用のツールを使いましょう。
  • alter table したら、整合性が取れるように修正しましょう。

この記事に書かないこと

oak-online-alter-tablept-online-schema-changeの細かい使い方については説明しません。どちらも公式ドキュメントが充実していますし、説明している良記事がWebにあるので、そちらを参照してください。

方針

Railsのプロジェクトは内部的に schema_migrations というテーブルを用意して、そこに実行済みのmigrationファイルのタイムスタンプを入れています。 rake db:migrate ではこのテーブルに 無い migrationファイルを実行したのちに、そのタイムスタンプをテーブルに追加します。

なので、手動で rake db:migrate を実行する代わりに、手動でmigrationファイル相当の処理を実行したのちに、対応するタイムスタンプを schema_migrations に追加すれば、あたかもRailsのmigration機能を使ったかのごとくDBに手を加えることができます。

流れ

  1. migrationファイルを書く
  2. developmentでrake db:migrate実行する。
  3. productionにツールを使って alter table を実行する
  4. productionの schema_migrations に1で作ったmigrationファイルのタイムスタンプを追加する

migrationファイルを書く

まずは何はともあれmigrationファイルを書きます。ここでは仮に users テーブルの name カラムにインデックスを追加するものとします。

db/migrate/20160407191432_add_index_to_users.rb
class AddIndexToUsers < ActiveRecord::Migration
  def change
    add_index :users, [:name]
  end
end

developmentでdb:migrateを実行する

migrationファイルができたら、これもいつも通りdevelopment環境で rake db:migrate を実行します。これはdb/schema.rbを更新するために行います。

ここまでやったらgit的にはコミットしてしまって問題ありませんが、この状態でデプロイすると通常通りのmigrationが走ってしまうので絶対にデプロイしてはいけません。

productionにツールを使ってalter tableを実行する

世の中には大きなテーブルに alter table を実行するためのツールがいくつか存在するのでそれを使います。

あたりが有名ドコロです。詳しい使い方はググッてください。

productionのschema_migrationsにタイムスタンプを追加する

schema_migrations にタイムスタンプを追加します。タイムスタンプというのはmigrationファイルの先頭にある数字の部分のことで、今回はファイル名が "20160407191432_add_index_to_users.rb" なので、タイムスタンプは "20160407191432" になります。

36
28
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
36
28