Skip to content

Instantly share code, notes, and snippets.

@jmgarnier
Last active August 29, 2015 14:21
Show Gist options
  • Save jmgarnier/e32a13949c7de0d1f8d7 to your computer and use it in GitHub Desktop.
Save jmgarnier/e32a13949c7de0d1f8d7 to your computer and use it in GitHub Desktop.
Postgres "EXPLAIN ANALYZE" from Rails 3.2 console with syntax hightlighting
if Rails.env.development?
require 'active_record/connection_adapters/postgresql_adapter'
require 'pygments' # add `gem 'pygments.rb', require: false` to Gemfile
module ExplainAnalyze
@@use_explain_analyze = false
def explain_analyze
@@use_explain_analyze = true
self
end
def explain_analyze?
@@use_explain_analyze
end
def no_more_explain_analyze
@@use_explain_analyze = false
end
end
ActiveRecord::Base.extend ExplainAnalyze
class ActiveRecord::ConnectionAdapters::PostgreSQLAdapter
def execute_with_explain_analyze(sql, *args)
__explain_analyze(sql, :execute, *args)
end
def exec_query_with_explain_analyze(sql, *args)
__explain_analyze(sql, :exec_query, *args)
end
def __explain_analyze(sql, command, *args)
original_method = "#{command}_without_explain_analyze".to_sym
if explain_analyze? && select_query?(sql)
ActiveRecord::Base.no_more_explain_analyze
puts "QUERY PLAN FOR:"
puts highlight_syntax(sql)
new_sql = "EXPLAIN ANALYZE #{sql}"
plan = send(original_method, new_sql, *args).map do |row|
row['QUERY PLAN']
end.join("\n")
puts highlight_syntax(plan)
end
send(original_method, sql, *args)
end
alias_method_chain :execute, :explain_analyze
alias_method_chain :exec_query, :explain_analyze
private
def explain_analyze?
ActiveRecord::Base.explain_analyze?
end
def select_query?(sql)
/\A\s*SELECT/i.match(sql)
end
def highlight_syntax(sql)
Pygments.highlight(sql, formatter:'terminal', lexer: 'sql')
end
end
end
@jmgarnier
Copy link
Author

Hacked with Ruby 2.1.5 and Rails 3.2. Inspired by James Sander's gist

Use fantastic pygments.rb for syntax highlighting in the console.

Usage:

User.explain_analyze.count

Output

QUERY PLAN FOR:
SELECT COUNT(*) FROM "users"
   (61.8ms)  EXPLAIN ANALYZE SELECT COUNT(*) FROM "users"
Aggregate  (cost=11599.81..11599.82 rows=1 width=0) (actual time=60.585..60.585 rows=1 loops=1)
  ->  Seq Scan on users  (cost=0.00..10826.25 rows=309425 width=0) (actual time=0.008..41.121 rows=309425 loops=1)
Total runtime: 60.621 ms
   (40.5ms)  SELECT COUNT(*) FROM "users"

@jmgarnier
Copy link
Author

I am not very happy with the @@use_explain_analyze, it was a quick 1 hour hack. Any idea how to improve it?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment