Module: ActiveRecord::Explain
Class Method Summary collapse
Instance Method Summary collapse
-
#collecting_queries_for_explain ⇒ Object
Relation#explain needs to be able to collect the queries regardless of whether auto explain is enabled.
-
#exec_explain(queries) ⇒ Object
Makes the adapter execute EXPLAIN for the tuples of queries and bindings.
-
#logging_query_plan ⇒ Object
If auto explain is enabled, this method triggers EXPLAIN logging for the queries triggered by the block if it takes more than the threshold as a whole.
-
#silence_auto_explain ⇒ Object
Silences automatic EXPLAIN logging for the duration of the block.
Class Method Details
.extended(base) ⇒ Object
5 6 7 8 9 10 11 12 |
# File 'lib/active_record/explain.rb', line 5 def self.extended(base) base.class_eval do # If a query takes longer than these many seconds we log its query plan # automatically. nil disables this feature. class_attribute :auto_explain_threshold_in_seconds, :instance_writer => false self.auto_explain_threshold_in_seconds = nil end end |
Instance Method Details
#collecting_queries_for_explain ⇒ Object
Relation#explain needs to be able to collect the queries regardless of whether auto explain is enabled. This method serves that purpose.
46 47 48 49 50 51 52 53 |
# File 'lib/active_record/explain.rb', line 46 def collecting_queries_for_explain # :nodoc: current = Thread.current original, current[:available_queries_for_explain] = current[:available_queries_for_explain], [] return yield, current[:available_queries_for_explain] ensure # Note that the return value above does not depend on this assigment. current[:available_queries_for_explain] = original end |
#exec_explain(queries) ⇒ Object
Makes the adapter execute EXPLAIN for the tuples of queries and bindings. Returns a formatted string ready to be logged.
57 58 59 60 61 62 63 64 65 66 67 68 |
# File 'lib/active_record/explain.rb', line 57 def exec_explain(queries) # :nodoc: queries && queries.map do |sql, bind| [].tap do |msg| msg << "EXPLAIN for: #{sql}" unless bind.empty? bind_msg = bind.map {|col, val| [col.name, val]}.inspect msg.last << " #{bind_msg}" end msg << connection.explain(sql, bind) end.join("\n") end.join("\n") end |
#logging_query_plan ⇒ Object
If auto explain is enabled, this method triggers EXPLAIN logging for the queries triggered by the block if it takes more than the threshold as a whole. That is, the threshold is not checked against each individual query, but against the duration of the entire block. This approach is convenient for relations.
The available_queries_for_explain thread variable collects the queries to be explained. If the value is nil, it means queries are not being currently collected. A false value indicates collecting is turned off. Otherwise it is an array of queries.
24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
# File 'lib/active_record/explain.rb', line 24 def logging_query_plan # :nodoc: return yield unless logger threshold = auto_explain_threshold_in_seconds current = Thread.current if threshold && current[:available_queries_for_explain].nil? begin queries = current[:available_queries_for_explain] = [] start = Time.now result = yield logger.warn(exec_explain(queries)) if Time.now - start > threshold result ensure current[:available_queries_for_explain] = nil end else yield end end |
#silence_auto_explain ⇒ Object
Silences automatic EXPLAIN logging for the duration of the block.
This has high priority, no EXPLAINs will be run even if downwards the threshold is set to 0.
As the name of the method suggests this only applies to automatic EXPLAINs, manual calls to ActiveRecord::Relation#explain run.
77 78 79 80 81 82 83 |
# File 'lib/active_record/explain.rb', line 77 def silence_auto_explain current = Thread.current original, current[:available_queries_for_explain] = current[:available_queries_for_explain], false yield ensure current[:available_queries_for_explain] = original end |