如何显示在 Rails 控制台中运行的 SQL 查询?

当我在控制台中运行查询(例如 MyModel.where(...)record.associated_things)时,我如何才能看到正在运行的实际数据库查询,以便更好地理解正在发生的事情?

104907 次浏览

Rails 3 +

在控制台中输入以下行:

ActiveRecord::Base.logger = Logger.new(STDOUT)

铁路2

在控制台中输入以下行:

ActiveRecord::Base.connection.instance_variable_set :@logger, Logger.new(STDOUT)

在 Rails 3 + 中,你可以使用 ActiveRecord: : Relations 的 to_sql方法:

User.where(:id => 3).to_sql
#=> "SELECT \"users\".* FROM \"users\"  WHERE \"users\".\"id\" = 3"

Rails 4中有 .explain方法。
(.to_sql也可以,但不会显示包括)

Category.includes(:products).explain
=> EXPLAIN for: SELECT "categories".* FROM "categories" 0|0|0|SCAN TABLE categories


EXPLAIN for: SELECT "categories_products".* FROM "categories_products" WHERE "categories_products"."category_id" IN (1, 2) 0|0|0|SCAN TABLE categories_products


EXPLAIN for: SELECT "products".* FROM "products" WHERE "products"."id" IN (1, 2, 3, 4, 5, 6, 7) 0|0|0|SEARCH TABLE products USING INTEGER PRIMARY KEY (rowid=?) 0|0|0|EXECUTE LIST SUBQUERY 1

从最近开始,你可以使用这个:

Https://github.com/dejan/rails_panel

它由开发者控制台面板附加的 chrome 和 gem 文件组成,这些文件需要像下面这样添加到你的应用程序的 Gemfile中:

group :development do
gem 'meta_request'
end

然后再跑:

bundle install

重新启动您的应用程序,打开它,并启动开发人员控制台,您应该看到如下所示: enter image description here

我更喜欢在 config/application.rb中设置日志记录器级别:

config.after_initialize do
Rails.logger.level = (ENV['LOG_LEVEL'] || Logger::INFO).to_i
end

在生产中,我的 ENV['LOG_LEVEL']将被设置为 Logger::INFO的值,在我的本地机器上它将是 Logger::DEBUG

从 Rails 6开始,有一种更方便的方法: 在控制台中简单地添加 ActiveRecord::Base.verbose_query_logs = true,您将看到所有 SQL 调用和它被调用的位置。更多信息 https://guides.rubyonrails.org/debugging_rails_applications.html#verbose-query-logs

我只是想给我们的生产控制台提供与开发人员相同的行为,即所有 SQL 查询都报告给控制台。

Rails.logger.level = 0

3.0.3 :001 > Rails.logger.level = 0
=> 0
3.0.3 :002 > User.last
User Load (0.7ms)  SELECT `users`.* FROM `users` ORDER BY `users`.`id` DESC LIMIT 1
=> #<User:…>

有几个配置参数可以控制是否将 SQL 查询打印到日志中。

(这个答案是基于 Rails 6.0的。)

首先,确认日志记录器已配置,其 @logdev具有与预期相匹配的 @dev@filename

pry(main)> ActiveRecord::Base.logger


=> #<ActiveSupport::Logger:0x00007fd47b400900
...,
@logdev=
#<Logger::LogDevice:0x00007fd47b400a90
@binmode=false,
@dev=#<File:log/development.log>,
@filename="log/development.log",
...>,
...>

接下来,确保日志记录器级别设置为 DEBUG:

ActiveRecord::Base.logger.debug!

尝试运行查询以查看问题是否已修复:

> ActiveRecord::Base.connection.exec_query 'SELECT 1'
SQL (0.1ms)  SELECT 1

如果查询被打印到日志文件(例如 log/development.log)而不是控制台,那么您可能需要这样做:

ActiveRecord::Base.logger.extend(
ActiveSupport::Logger.broadcast(ActiveSupport::Logger.new(STDOUT))
)

如果您仍然没有收到 SQL 查询,那么 ActiveRecord::LogSubscriber可能没有监听事件(例如,因为一些库停用了它)。启动:

ActiveRecord::LogSubscriber.attach_to :active_record