lib/dexter/indexer.rb in pgdexter-0.3.1 vs lib/dexter/indexer.rb in pgdexter-0.3.2

- old
+ new

@@ -28,25 +28,15 @@ # reset hypothetical indexes reset_hypothetical_indexes tables = Set.new(database_tables) - if @include_tables - include_set = Set.new(@include_tables) - tables.keep_if { |t| include_set.include?(t) || include_set.include?(t.split(".")[-1]) } - end - - if @exclude_tables.any? - exclude_set = Set.new(@exclude_tables) - tables.delete_if { |t| exclude_set.include?(t) || exclude_set.include?(t.split(".")[-1]) } - end - # map tables without schema to schema no_schema_tables = {} search_path_index = Hash[search_path.map.with_index.to_a] tables.group_by { |t| t.split(".")[-1] }.each do |group, t2| - no_schema_tables[group] = t2.sort_by { |t| search_path_index[t.split(".")[0]] || 1000000 }[0] + no_schema_tables[group] = t2.sort_by { |t| [search_path_index[t.split(".")[0]] || 1000000, t] }[0] end # filter queries from other databases and system tables queries.each do |query| # add schema to table if needed @@ -57,15 +47,33 @@ end # set tables tables = Set.new(queries.reject(&:missing_tables).flat_map(&:tables)) + # must come after missing tables set + if @include_tables + include_set = Set.new(@include_tables) + tables.keep_if { |t| include_set.include?(t) || include_set.include?(t.split(".")[-1]) } + end + + if @exclude_tables.any? + exclude_set = Set.new(@exclude_tables) + tables.delete_if { |t| exclude_set.include?(t) || exclude_set.include?(t.split(".")[-1]) } + end + + # remove system tables + tables.delete_if { |t| t.start_with?("information_schema.") || t.start_with?("pg_catalog.") } + + queries.each do |query| + query.candidate_tables = !query.missing_tables && query.tables.any? { |t| tables.include?(t) } + end + # analyze tables if needed analyze_tables(tables) if tables.any? && (@analyze || @log_level == "debug2") # create hypothetical indexes and explain queries - candidates = tables.any? ? create_hypothetical_indexes(queries.reject(&:missing_tables), tables) : {} + candidates = tables.any? ? create_hypothetical_indexes(queries.select(&:candidate_tables), tables) : {} # see if new indexes were used and meet bar new_indexes = determine_indexes(queries, candidates, tables) # display and create new indexes @@ -342,29 +350,30 @@ end index_queries.each do |query| log "-" * 80 log "Query #{query.fingerprint}" log "Total time: #{(query.total_time / 60000.0).round(1)} min, avg time: #{(query.total_time / query.calls.to_f).round} ms, calls: #{query.calls}" if query.total_time - if tables.empty? + + if query.fingerprint == "unknown" + log "Could not parse query" + elsif query.tables.empty? + log "No tables" + elsif query.missing_tables + log "Tables not present in current database" + elsif !query.candidate_tables log "No candidate tables for indexes" elsif query.explainable? && !query.high_cost? log "Low initial cost: #{query.initial_cost}" elsif query.explainable? query_indexes = query.indexes || [] log "Start: #{query.costs[0]}" log "Pass1: #{query.costs[1]} : #{log_indexes(query.pass1_indexes || [])}" log "Pass2: #{query.costs[2]} : #{log_indexes(query.pass2_indexes || [])}" log "Final: #{query.new_cost} : #{log_indexes(query.suggest_index ? query_indexes : [])}" - if query_indexes.any? && !query.suggest_index + if query_indexes.size == 1 && !query.suggest_index log "Need 50% cost savings to suggest index" end - elsif query.fingerprint == "unknown" - log "Could not parse query" - elsif query.tables.empty? - log "No tables" - elsif query.missing_tables - log "Tables not present in current database" else log "Could not run explain" end log log query.statement @@ -450,13 +459,11 @@ SELECT table_schema || '.' || table_name AS table_name FROM information_schema.tables WHERE - table_catalog = current_database() AND - table_schema NOT IN ('pg_catalog', 'information_schema') - AND table_type = 'BASE TABLE' + table_catalog = current_database() SQL result.map { |r| r["table_name"] } end def stat_statements @@ -547,10 +554,10 @@ SQL ).map { |v| v["columns"] = v["columns"].sub(") WHERE (", " WHERE ").split(", ").map { |c| unquote(c) }; v } end def search_path - execute("SHOW search_path")[0]["search_path"].split(",").map(&:strip) + execute("SELECT current_schemas(true)")[0]["current_schemas"][1..-2].split(",") end def unquote(part) if part && part.start_with?('"') && part.end_with?('"') part[1..-2]