Class: Shiba::IndexStats

Inherits:
Object
  • Object
show all
Defined in:
lib/shiba/index_stats.rb

Defined Under Namespace

Classes: Column, Index, Table

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(tables = {}) ⇒ IndexStats

Returns a new instance of IndexStats.



7
8
9
10
# File 'lib/shiba/index_stats.rb', line 7

def initialize(tables = {})
  @tables = tables
  build_from_hash!
end

Instance Attribute Details

#tablesObject (readonly)

Returns the value of attribute tables.



147
148
149
# File 'lib/shiba/index_stats.rb', line 147

def tables
  @tables
end

Instance Method Details

#add_index_column(table, index_name, column_name, cardinality, is_unique) ⇒ Object



164
165
166
167
# File 'lib/shiba/index_stats.rb', line 164

def add_index_column(table, index_name, column_name, cardinality, is_unique)
  table = build_table(table)
  table.add_index_column(index_name, column_name, nil, cardinality, is_unique)
end

#any?Boolean

Returns:

  • (Boolean)


12
13
14
# File 'lib/shiba/index_stats.rb', line 12

def any?
  @tables.any?
end

#build_from_hash!Object



135
136
137
138
139
140
141
142
143
144
145
# File 'lib/shiba/index_stats.rb', line 135

def build_from_hash!
  @tables = @tables.collect do |tbl_name, tbl_hash|
    t = Table.new(tbl_name, tbl_hash['count'], {})
    tbl_hash['indexes'].each do |idx_name, idx_hash|
      idx_hash['columns'].each do |col_hash|
        t.add_index_column(idx_name, col_hash['column'], col_hash['rows_per'], nil, idx_hash['unique'])
      end
    end
    [tbl_name, t]
  end.to_h
end

#build_table(name) ⇒ Object



160
161
162
# File 'lib/shiba/index_stats.rb', line 160

def build_table(name)
  @tables[name] ||= Table.new(name, nil, {})
end

#convert_rows_per_to_output!Object



206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
# File 'lib/shiba/index_stats.rb', line 206

def convert_rows_per_to_output!
  each_index_column do |table, column|
    cardinality = column.delete('cardinality')

    if table.rows == 0
      column['rows_per'] = 1
      next
    end

    # the bigger the table, the more likely we should be
    # to show percentages for larger counts.
    #
    # small table, show row count up to 10% ish
    # 100_000 - show rows up to 1000, 1%
    # large table, 1_000_000.  show rows up to 0.1% ( 1000 )


    # how many rows does each index value contain?
    if cardinality
      rows_per_item = (table.rows.to_f / cardinality.to_f)
    else
      rows_per_item = column.rows_per
    end

  end
end

#estimate_key(table_name, key, parts) ⇒ Object



187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
# File 'lib/shiba/index_stats.rb', line 187

def estimate_key(table_name, key, parts)
  index = fetch_index(table_name, key)

  return nil unless index

  index_part = nil
  index.columns.each do |c|
    break unless parts.include?(c.column)
    index_part = c
  end

  # postgres can claim to use the right hand side of an index
  # in a bitmap scan, which seems to be a side-effect of forcing
  # seq-scan off.  In these cases we'll say it's a full scan.
  return table_count(table_name) unless index_part

  index_part.rows_per
end

#fetch_index(table, name) ⇒ Object



153
154
155
156
157
158
# File 'lib/shiba/index_stats.rb', line 153

def fetch_index(table, name)
  tbl = find_table(table)
  return nil unless tbl

  tbl.indexes[name]
end

#find_table(name) ⇒ Object

case insenstive table match



17
18
19
20
21
22
23
# File 'lib/shiba/index_stats.rb', line 17

def find_table(name)
  table = @tables[name]
  return table if table

  _, table = @tables.detect { |k,_| k.casecmp(name).zero? }
  return table
end

#get_column_size(table_name, column) ⇒ Object



169
170
171
172
173
174
# File 'lib/shiba/index_stats.rb', line 169

def get_column_size(table_name, column)
  table = find_table(table_name)
  return nil unless table

  table.column_sizes[column]
end

#set_column_size(table_name, column, size) ⇒ Object



176
177
178
179
180
181
182
183
184
185
# File 'lib/shiba/index_stats.rb', line 176

def set_column_size(table_name, column, size)
  if !@tables[table_name]
    # we get here when a table has no indices.  Should really do something smarter long term,
    # as we'll have zero-counts, stuff like that.
    build_table(table_name)
  end

  table = @tables[table_name]
  table.column_sizes[column] = size
end

#table_count(table) ⇒ Object



149
150
151
# File 'lib/shiba/index_stats.rb', line 149

def table_count(table)
  return find_table(table).count if find_table(table)
end

#to_yamlObject



233
234
235
# File 'lib/shiba/index_stats.rb', line 233

def to_yaml
  @tables.to_yaml
end