module PgsqlStats class Table include PgsqlStats::Parsing include ActionView::Helpers::NumberHelper attr_accessor :oid, :schema_name, :name, :sequential_scans, :rows_fetched, :index_scans, :index_rows_fetched, :inserts, :updates, :deletes, :vacuumed_at, :autovacuumed_at, :analyzed_at, :autoanalyzed_at, :blocks_read, :cache_hits, :index_blocks_read, :index_cache_hits, :toast_blocks_read, :toast_cache_hits, :toast_index_blocks_read, :toast_index_cache_hits attr_accessor :analysis def initialize(connection, row, io_row) @connection = connection @analysis = nil load(row) load_io(io_row) end def refresh @connection.transaction do load(@connection.select_one("SELECT * FROM pg_stat_all_tables WHERE relid = #{oid}")) load_io(@connection.select_one("SELECT * FROM pg_statio_all_tables WHERE relid = #{oid}")) end @analysis = nil @pages = nil @indexes = nil end def indexes unless @indexes old_conn, Collector.connection = Collector.connection, @connection @indexes = Collector.all_indexes(oid) Collector.connection = old_conn end @indexes end def cache_hit_rate cache_hits.to_f / (blocks_read + cache_hits) * 100 end def index_cache_hit_rate index_cache_hits.to_f / (index_blocks_read + index_cache_hits) * 100 end def toast_cache_hit_rate toast_cache_hits.to_f / (toast_blocks_read + toast_cache_hits) * 100 end def toast_index_cache_hit_rate toast_index_cache_hits.to_f / (toast_index_blocks_read + toast_index_cache_hits) * 100 end def pages @pages ||= @connection.select_one("SELECT SUM(relpages) FROM pg_class WHERE relname = '#{name}'")["sum"].to_i end private def load(row) self.oid = row["relid"].to_i self.schema_name = row["schemaname"] self.name = row["relname"] self.sequential_scans = row["seq_scan"].to_i self.rows_fetched = row["seq_tup_read"].to_i self.index_scans = row["idx_scan"].to_i self.index_rows_fetched = row["idx_tup_fetch"].to_i self.inserts = row["n_tup_ins"].to_i self.updates = row["n_tup_upd"].to_i self.deletes = row["n_tup_del"].to_i self.vacuumed_at = parse_time(row["last_vacuum"]) self.autovacuumed_at = parse_time(row["last_autovacuum"]) self.analyzed_at = parse_time(row["last_analyze"]) self.autoanalyzed_at = parse_time(row["last_autoanalyze"]) end def load_io(row) self.blocks_read = row["heap_blks_read"].to_i self.cache_hits = row["heap_blks_hit"].to_i self.index_blocks_read = row["idx_blks_read"].to_i self.index_cache_hits = row["idx_blks_hit"].to_i self.toast_blocks_read = row["toast_blks_read"].to_i self.toast_cache_hits = row["toast_blks_hit"].to_i self.toast_index_blocks_read = row["tidx_blks_read"].to_i self.toast_index_cache_hits = row["tidx_blks_hit"].to_i end end end