How to add index to a large working app on Rails?
Well known fact is that PostgreSQL and many other RDBMS lock write access on the table while the index is being created. It is not acceptable when your project is large enough to allow a downtime for such the small adjustment like a new index.
There is a way to avoid the write-lock though. You can create the index concurrently. But how to do it with Rails Migrations?
First of all you can pass
class AddIndexOnBatchIdToFundTrades < ActiveRecord::Migration[5.0] def change add_index :fund_trades, :batch_id, algorithm: :concurrently end end
But when you try to run such the migration, you would get the following error:
PG::ActiveSqlTransaction: ERROR: CREATE INDEX CONCURRENTLY cannot run inside a transaction block : CREATE INDEX CONCURRENTLY "index_fund_trades_on_batch_id" ON "fund_trades" ("batch_id")
That's because any migration by default is executed inside a transaction. Thankfully there is a way to pass it through - use
disable_ddl_transaction! to run your migration without a transaction:
class AddIndexOnBatchIdToFundTrades < ActiveRecord::Migration[5.0] disable_ddl_transaction! def change add_index :fund_trades, :batch_id, algorithm: :concurrently end end