Class: Dexter::Indexer

Inherits:
Object
  • Object
show all
Includes:
Logging
Defined in:
lib/dexter/indexer.rb

Constant Summary

Constants included from Logging

Logging::COLOR_CODES

Instance Method Summary collapse

Methods included from Logging

#colorize, #log, #output

Constructor Details

#initialize(connection:, **options) ⇒ Indexer

Returns a new instance of Indexer.



5
6
7
8
9
10
11
12
13
14
15
16
17
18
# File 'lib/dexter/indexer.rb', line 5

def initialize(connection:, **options)
  @connection = connection
  @create = options[:create]
  @tablespace = options[:tablespace]
  @log_level = options[:log_level]
  @exclude_tables = options[:exclude]
  @include_tables = Array(options[:include].split(",")) if options[:include]
  @log_explain = options[:log_explain]
  @analyze = options[:analyze]
  @min_cost = options[:min_cost].to_i
  @min_cost_savings_pct = options[:min_cost_savings_pct].to_i
  @options = options
  @server_version_num = @connection.server_version_num
end

Instance Method Details

#process_queries(queries) ⇒ Object

TODO recheck server version?



21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
# File 'lib/dexter/indexer.rb', line 21

def process_queries(queries)
  TableResolver.new(@connection, queries, log_level: @log_level).perform
  candidate_queries = queries.reject(&:missing_tables)

  tables = determine_tables(candidate_queries)
  candidate_queries.each do |query|
    query.candidate_tables = query.tables.select { |t| tables.include?(t) }.sort
  end
  candidate_queries.select! { |q| q.candidate_tables.any? }

  if tables.any?
    # analyze tables if needed
    # TODO remove @log_level in 0.7.0
    analyze_tables(tables) if @analyze || @log_level == "debug2"

    # get initial costs for queries
    reset_hypothetical_indexes
    calculate_plan(candidate_queries)
    candidate_queries.select! { |q| q.initial_cost && q.initial_cost >= @min_cost }

    # find columns
    ColumnResolver.new(@connection, candidate_queries, log_level: @log_level).perform
    candidate_queries.each do |query|
      # no reason to use btree index for json columns
      # TODO check type supports btree
      query.candidate_columns = query.columns.reject { |c| ["json", "jsonb", "point"].include?(c[:type]) }.sort_by { |c| [c[:table], c[:column]] }
    end
    candidate_queries.select! { |q| q.candidate_columns.any? }

    # create hypothetical indexes and explain queries
    batch_hypothetical_indexes(candidate_queries)
  end

  # see if new indexes were used and meet bar
  new_indexes = determine_indexes(queries, tables)

  # display new indexes
  show_new_indexes(new_indexes)

  # display debug info
  show_debug_info(new_indexes, queries) if @log_level.start_with?("debug")

  # create new indexes
  IndexCreator.new(@connection, self, new_indexes, @tablespace).perform if @create && new_indexes.any?
end