diff options
author | Akira Matsuda & Naoto Koshikawa <ronnie@dio.jp> | 2016-01-27 17:44:27 +0900 |
---|---|---|
committer | Akira Matsuda <ronnie@dio.jp> | 2016-01-27 18:17:13 +0900 |
commit | 42dd2336b31a8d98776d039a2b9fd7f834156a78 (patch) | |
tree | dcf28e1b837a08b39b452f98c9e3e14e5f2bd6df | |
parent | 3844854af109fb9eee75c90bacf8bf87eb2bf968 (diff) | |
download | rails-42dd2336b31a8d98776d039a2b9fd7f834156a78.tar.gz rails-42dd2336b31a8d98776d039a2b9fd7f834156a78.tar.bz2 rails-42dd2336b31a8d98776d039a2b9fd7f834156a78.zip |
INSERT INTO schema_migrations in 1 SQL
We found that inserting all 600 schema_migrations for our mid-sized app takes about a minute on a cloud based CI environment.
I assume that the original code did not use multi-row-insert because SQLite3 was not supporting the syntax back then,
but it's been supported since 3.7.11: http://www.sqlite.org/releaselog/3_7_11.html
-rw-r--r-- | activerecord/CHANGELOG.md | 5 | ||||
-rw-r--r-- | activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb | 18 |
2 files changed, 13 insertions, 10 deletions
diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md index f3dc26ddb3..b59c9b4635 100644 --- a/activerecord/CHANGELOG.md +++ b/activerecord/CHANGELOG.md @@ -1,3 +1,8 @@ +* Improve schema_migrations insertion performance by inserting all versions + in one INSERT SQL. + + *Akira Matsuda*, *Naoto Koshikawa* + * Using `references` or `belongs_to` in migrations will always add index for the referenced column by default, without adding `index: true` option to generated migration file. Users can opt out of this by passing diff --git a/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb b/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb index 70868ebd03..002f2ea8ce 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb @@ -957,9 +957,9 @@ module ActiveRecord def dump_schema_information #:nodoc: sm_table = ActiveRecord::Migrator.schema_migrations_table_name - ActiveRecord::SchemaMigration.order('version').map { |sm| - "INSERT INTO #{sm_table} (version) VALUES ('#{sm.version}');" - }.join "\n\n" + sql = "INSERT INTO #{sm_table} (version) VALUES " + sql << ActiveRecord::SchemaMigration.order('version').pluck(:version).map {|v| "('#{v}')" }.join(', ') + sql << ";\n\n" end # Should not be called normally, but this operation is non-destructive. @@ -987,14 +987,12 @@ module ActiveRecord execute "INSERT INTO #{sm_table} (version) VALUES ('#{version}')" end - inserted = Set.new - (versions - migrated).each do |v| - if inserted.include?(v) - raise "Duplicate migration #{v}. Please renumber your migrations to resolve the conflict." - elsif v < version - execute "INSERT INTO #{sm_table} (version) VALUES ('#{v}')" - inserted << v + inserting = (versions - migrated).select {|v| v < version} + if inserting.any? + if (duplicate = inserting.detect {|v| inserting.count(v) > 1}) + raise "Duplicate migration #{duplicate}. Please renumber your migrations to resolve the conflict." end + execute "INSERT INTO #{sm_table} (version) VALUES #{inserting.map {|v| '(#{v})'}.join(', ') }" end end |