diff options
author | Andreas Brandl <abrandl@gitlab.com> | 2018-10-28 17:50:44 +0300 |
---|---|---|
committer | Andreas Brandl <abrandl@gitlab.com> | 2018-12-03 23:26:47 +0300 |
commit | f3a931517735268487dfee9a129280dc06835fad (patch) | |
tree | b8936f66d16c946bb94cfe5f18168fb3e993abe1 /lib/gitlab/database | |
parent | c3c25174e3397ca3f301b539477e6568c676d264 (diff) |
Extract ReltuplesCountStrategy.
Diffstat (limited to 'lib/gitlab/database')
-rw-r--r-- | lib/gitlab/database/count.rb | 57 |
1 files changed, 37 insertions, 20 deletions
diff --git a/lib/gitlab/database/count.rb b/lib/gitlab/database/count.rb index ea6529e2dc4..fc61ee48832 100644 --- a/lib/gitlab/database/count.rb +++ b/lib/gitlab/database/count.rb @@ -54,34 +54,51 @@ module Gitlab # @param [Array] table names # @returns [Hash] Table name to count mapping (e.g. { 'projects' => 5, 'users' => 100 }) def self.reltuples_from_recently_updated(table_names) - query = postgresql_estimate_query(table_names) - rows = [] + ReltuplesCountStrategy.new(table_names).count + end + + class ReltuplesCountStrategy + attr_reader :table_names - # Querying tuple stats only works on the primary. Due to load - # balancing, we need to ensure this query hits the load balancer. The - # easiest way to do this is to start a transaction. - ActiveRecord::Base.transaction do - rows = ActiveRecord::Base.connection.select_all(query) + # @param [Array] table names + def initialize(table_names) + @table_names = table_names end - rows.each_with_object({}) { |row, data| data[row['table_name']] = row['estimate'].to_i } - rescue *CONNECTION_ERRORS - {} - end + # Returns a hash of the table names that have recently updated tuples. + # + # @returns [Hash] Table name to count mapping (e.g. { 'projects' => 5, 'users' => 100 }) + def count + query = postgresql_estimate_query(table_names) + rows = [] - # Generates the PostgreSQL query to return the tuples for tables - # that have been vacuumed or analyzed in the last hour. - # - # @param [Array] table names - # @returns [Hash] Table name to count mapping (e.g. { 'projects' => 5, 'users' => 100 }) - def self.postgresql_estimate_query(table_names) - time = "to_timestamp(#{1.hour.ago.to_i})" - <<~SQL + # Querying tuple stats only works on the primary. Due to load + # easiest way to do this is to start a transaction. + ActiveRecord::Base.transaction do + rows = ActiveRecord::Base.connection.select_all(query) + end + + rows.each_with_object({}) { |row, data| data[row['table_name']] = row['estimate'].to_i } + rescue *CONNECTION_ERRORS => e + {} + end + + private + + # Generates the PostgreSQL query to return the tuples for tables + # that have been vacuumed or analyzed in the last hour. + # + # @param [Array] table names + # @returns [Hash] Table name to count mapping (e.g. { 'projects' => 5, 'users' => 100 }) + def postgresql_estimate_query(table_names) + time = "to_timestamp(#{1.hour.ago.to_i})" + <<~SQL SELECT pg_class.relname AS table_name, reltuples::bigint AS estimate FROM pg_class LEFT JOIN pg_stat_user_tables ON pg_class.relname = pg_stat_user_tables.relname WHERE pg_class.relname IN (#{table_names.map { |table| "'#{table}'" }.join(',')}) AND (last_vacuum > #{time} OR last_autovacuum > #{time} OR last_analyze > #{time} OR last_autoanalyze > #{time}) - SQL + SQL + end end end end |