Commit cb8f648c authored by Grzegorz Bizon's avatar Grzegorz Bizon

Add tmp index to ci_builds to optimize stages migration

parent 3d93ad10
...@@ -2,6 +2,7 @@ class CleanupBuildStageMigration < ActiveRecord::Migration ...@@ -2,6 +2,7 @@ class CleanupBuildStageMigration < ActiveRecord::Migration
include Gitlab::Database::MigrationHelpers include Gitlab::Database::MigrationHelpers
DOWNTIME = false DOWNTIME = false
TMP_INDEX = 'tmp_id_stage_partial_null_index'.freeze
disable_ddl_transaction! disable_ddl_transaction!
...@@ -13,16 +14,48 @@ class CleanupBuildStageMigration < ActiveRecord::Migration ...@@ -13,16 +14,48 @@ class CleanupBuildStageMigration < ActiveRecord::Migration
end end
def up def up
disable_statement_timeout
##
# We steal from the background migrations queue to catch up with the
# scheduled migrations set.
#
Gitlab::BackgroundMigration.steal('MigrateBuildStage') Gitlab::BackgroundMigration.steal('MigrateBuildStage')
##
# We add temporary index, to make iteration over batches more performant.
# Conditional here is to avoid the need of doing that in a separate
# migration file to make this operation idempotent.
#
unless index_exists_by_name?(:ci_builds, TMP_INDEX)
add_concurrent_index(:ci_builds, :id, where: 'stage_id IS NULL', name: TMP_INDEX)
end
##
# We check if there are remaining rows that should be migrated (for example
# if Sidekiq / Redis fails / is restarted, what could result in not all
# background migrations being executed correctly.
#
# We migrate remaining rows synchronously in a blocking way, to make sure
# that when this migration is done we are confident that all rows are
# already migrated.
#
Build.where('stage_id IS NULL').each_batch(of: 50) do |batch| Build.where('stage_id IS NULL').each_batch(of: 50) do |batch|
range = batch.pluck('MIN(id)', 'MAX(id)').first range = batch.pluck('MIN(id)', 'MAX(id)').first
Gitlab::BackgroundMigration::MigrateBuildStage.new.perform(*range) Gitlab::BackgroundMigration::MigrateBuildStage.new.perform(*range)
end end
##
# We remove temporary index, because it is not required during standard
# operations and runtime.
#
remove_concurrent_index_by_name(:ci_builds, TMP_INDEX)
end end
def down def down
# noop if index_exists_by_name?(:ci_builds, TMP_INDEX)
remove_concurrent_index_by_name(:ci_builds, TMP_INDEX)
end
end end
end end
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment