计算执行的查询数 [英] Counting the number of queries performed

查看:62
本文介绍了计算执行的查询数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想测试某段代码执行尽可能少的SQL查询.

I'd like to test that a certain piece of code performs as few SQL queries as possible.

ActiveRecord::TestCase似乎有其自己的assert_queries方法,该方法可以做到这一点.但是由于我没有修补ActiveRecord,所以对我来说没什么用.

ActiveRecord::TestCase seems to have its own assert_queries method, which will do just that. But since I'm not patching ActiveRecord, it's of little use to me.

RSpec或ActiveRecord是否提供任何官方的,公开的方法来计算在代码块中执行的SQL查询的数量?

Does RSpec or ActiveRecord provide any official, public means of counting the number of SQL queries performed in a block of code?

推荐答案

我认为您通过提及assert_queries来回答了自己的问题,但是这里有:

I think you answered your own question by mentioning assert_queries, but here goes:

我建议您看一下assert_queries背后的代码,并使用它来构建自己的方法,该方法可用于对查询进行计数.这里涉及的主要魔术是这一行:

I would recommend taking a look at the code behind assert_queries and using that to build your own method which you can use to count queries. The main magic involved here is this line:

ActiveSupport::Notifications.subscribe('sql.active_record', SQLCounter.new)

今天早上,我有点麻烦了,并且删除了ActiveRecord进行查询计数的部分,并提出了以下建议:

I had a bit of a tinker this morning and ripped out the parts of ActiveRecord that do the query counting and came up with this:

module ActiveRecord
  class QueryCounter
    cattr_accessor :query_count do
      0
    end

    IGNORED_SQL = [/^PRAGMA (?!(table_info))/, /^SELECT currval/, /^SELECT CAST/, /^SELECT @@IDENTITY/, /^SELECT @@ROWCOUNT/, /^SAVEPOINT/, /^ROLLBACK TO SAVEPOINT/, /^RELEASE SAVEPOINT/, /^SHOW max_identifier_length/]

    def call(name, start, finish, message_id, values)
      # FIXME: this seems bad. we should probably have a better way to indicate
      # the query was cached
      unless 'CACHE' == values[:name]
        self.class.query_count += 1 unless IGNORED_SQL.any? { |r| values[:sql] =~ r }
      end
    end
  end
end

ActiveSupport::Notifications.subscribe('sql.active_record', ActiveRecord::QueryCounter.new)

module ActiveRecord
  class Base
    def self.count_queries(&block)
      ActiveRecord::QueryCounter.query_count = 0
      yield
      ActiveRecord::QueryCounter.query_count
    end
  end
end

您将可以在任何地方引用ActiveRecord::Base.count_queries方法.向其传递一个运行查询的块,它将返回已执行的查询数:

You will be able to reference the ActiveRecord::Base.count_queries method anywhere. Pass it a block wherein your queries are run and it will return the number of queries that have been executed:

ActiveRecord::Base.count_queries do
  Ticket.first
end

为我返回"1".为此,请将其放在lib/active_record/query_counter.rb的文件中,并按如下所示在您的config/application.rb文件中要求它:

Returns "1" for me. To make this work: put it in a file at lib/active_record/query_counter.rb and require it in your config/application.rb file like this:

require 'active_record/query_counter'

嘿,谢谢!

可能需要一些解释.当我们呼叫这条线时:

A little bit of explanation probably is required. When we call this line:

    ActiveSupport::Notifications.subscribe('sql.active_record', ActiveRecord::QueryCounter.new)

我们加入了Rails 3的小通知框架.这是对Rails的最新主要版本的一个鲜有补充,鲜为人知.它允许我们使用subscribe方法订阅Rails中的事件通知.我们传入要订阅的事件作为第一个参数,然后将任何响应call的对象作为第二个参数.

We hook into Rails 3's little notifications framework. It's a shiny little addition to the latest major version of Rails that nobody really knows about. It allows us to subscribe to notifications of events within Rails by using the subscribe method. We pass in the event we want to subscribe to as the first argument then any object that responds to call as the second.

在这种情况下,当执行查询时,我们的小查询计数器将忠实地增加ActiveRecord :: QueryCounter.query_count变量,但仅适用于 real 查询.

In this case when a query is executed our little query counter will dutifully increment the ActiveRecord::QueryCounter.query_count variable, but only for the real queries.

无论如何,这很有趣.我希望它对您有用.

Anyway, this was fun. I hope it comes useful to you.

这篇关于计算执行的查询数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆