2021-02-22 17:27:13 +05:30
|
|
|
# frozen_string_literal: true
|
|
|
|
|
|
|
|
module Gitlab
|
|
|
|
module Database
|
|
|
|
module Reindexing
|
|
|
|
class IndexSelection
|
|
|
|
include Enumerable
|
|
|
|
|
2021-09-30 23:02:18 +05:30
|
|
|
# Only reindex indexes with a relative bloat level (bloat estimate / size) higher than this
|
|
|
|
MINIMUM_RELATIVE_BLOAT = 0.2
|
|
|
|
|
2021-12-11 22:18:48 +05:30
|
|
|
# Only consider indexes beyond this size (before reindexing)
|
|
|
|
INDEX_SIZE_MINIMUM = 1.gigabyte
|
2021-09-30 23:02:18 +05:30
|
|
|
|
2021-02-22 17:27:13 +05:30
|
|
|
delegate :each, to: :indexes
|
|
|
|
|
|
|
|
def initialize(candidates)
|
|
|
|
@candidates = candidates
|
|
|
|
end
|
|
|
|
|
|
|
|
private
|
|
|
|
|
|
|
|
attr_reader :candidates
|
|
|
|
|
|
|
|
def indexes
|
|
|
|
# This is an explicit N+1 query:
|
|
|
|
# Bloat estimates are generally available through a view
|
|
|
|
# for all indexes. However, estimating bloat for all
|
|
|
|
# indexes at once is an expensive operation. Therefore,
|
|
|
|
# we force a N+1 pattern here and estimate bloat on a per-index
|
|
|
|
# basis.
|
|
|
|
|
2021-09-30 23:02:18 +05:30
|
|
|
@indexes ||= candidates
|
|
|
|
.not_recently_reindexed
|
2021-12-11 22:18:48 +05:30
|
|
|
.where('ondisk_size_bytes >= ?', INDEX_SIZE_MINIMUM)
|
2021-09-30 23:02:18 +05:30
|
|
|
.sort_by(&:relative_bloat_level) # forced N+1
|
|
|
|
.reverse
|
|
|
|
.select { |candidate| candidate.relative_bloat_level >= MINIMUM_RELATIVE_BLOAT }
|
2021-02-22 17:27:13 +05:30
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|