【问题标题】:methods for debugging slow queries in active model serializers?在活动模型序列化程序中调试慢查询的方法?
【发布时间】:2016-05-14 16:55:35
【问题描述】:

我在优化我的 Active Model Serializer 以避免 n+1 问题时遇到了困难。根据他们的文档的建议,我试图加载我认为会导致查询瓶颈的关联,但我的序列化程序仍然需要永远。

显然,我一定做错了什么。我的应用程序深深地嵌套在关联中,所以我想我更感兴趣的是发现一种工具来准确地向我揭示哪些关联正在使我付出代价。现在,我将堆栈跟踪附加到通过 ActiveRecord 运行的每个查询

ActiveSupport::Notifications.subscribe("sql.active_record") do |_, _, _, _, details|
  puts caller.join("\n")
  puts "*" * 50
end

这给了我一个荒谬的输出,因为我一开始就运行了很多查询,但是,此外,堆栈跟踪对于识别哪个序列化程序有问题没有帮助。它向我显示了哪个控制器方法正在调用渲染,但随后堆栈跟踪仅打印来自 gems/active_model_serializers 的方法,这对我没有帮助。

我希望发现一种调试方法,能够向我识别哪些序列化程序有问题,这样我就不会猜测如何优化我的查询。有没有人发现过这样的事情?谢谢!

==================== 更新

很清楚,除了堆栈跟踪之外,我已经在打印查询日志了。不幸的是,有这么多的关联要跟踪,查询日志在识别查询源方面并不完全有帮助。这充其量只是猜测工作,在我正在处理的关联范围内无效。

我完全放弃了堆栈跟踪,发现它们完全没有帮助。现在,我打印的只是 SQL 日志,我正在手动筛选它们,试图发现关联的来源。

我将尝试的下一个方法(尽管我讨厌诉诸它)是注释掉关联,直到我看到查询时间有所改善。这将比试图追踪问题的根源更有效,但它不会让我在生产环境中感到舒适(注释掉关键关联不是一种选择),所以如果有人找到可以提供帮助的解决方案,我会还是很感激的。

在我解决这个问题时,我将继续发布更新,因为它可能会在未来帮助许多其他人。

=======================更新 2 事实证明,在我的序列化程序中注释掉关联并一次重新引入它们,虽然在生产中无效,但在本地环境中进行调试是一种很好的方式。我能够在一分钟内深入解决问题并纠正它。尽管如此,这并不是一个理想的解决方案。理想情况下,我希望能够从日志中识别问题,以便在生产中我可以在不影响应用程序行为的情况下确定问题。

【问题讨论】:

  • 寻求软件推荐的问题不在主题范围内。您可能想查看BulletRails Panel。 Rails 还有一个内置选项,可以将所有 SQL 查询打印到控制台。
  • 对不起!当然,你就在那里。我已从标题中删除了“推荐”一词的无效使用。问题的主体仍在寻求解决特定问题的方法。有没有更好的表达方式?还是在某些方面仍然无效?
  • 另外,如果您阅读该问题,您会看到我已经将所有查询打印到控制台。 :)
  • 是的,但有很多不那么骇人听闻的方法来做到这一点。 stackoverflow.com/questions/23397341/…
  • 我已经在使用 SQL 记录器,此外我正在打印每个查询条目的堆栈跟踪。 sql 记录器有些帮助,但很难看到杂散查询的来源。在不知道是什么关联触发它的情况下,这不是一门精确的科学。

标签: ruby-on-rails rails-activerecord active-model-serializers


【解决方案1】:

active_record_query_trace gem 可以做到这一点。

  1. 将以下内容添加到您的 Gemfile:
group :development do
  gem 'active_record_query_trace'
end
  1. 创建一个诸如config/initializers/active_record_query_trace.rb 的初始化器来启用gem。如果您想自定义 gem 的行为方式,您也可以将 docs 中描述的选项的任意组合添加到初始化程序中。
if Rails.env.development?
 ActiveRecordQueryTrace.enabled = true
 # Optional: other gem config options go here
end
  1. 重新启动 Rails 开发服务器。

【讨论】:

    【解决方案2】:

    在任何 gem 中的简单方法 - 记录每个代码字符串。例如,如果您有 序列化器的代码:

    module Flats
      class IndexSerializer < Api::V2::RealtyObjects::IndexSerializer
        attributes(
          :flat_number,
          :entrance_number,
          :floor_in_house,
          :live_area,
          :room_count,
          :total_area,
        )
      end
    end
    

    将记录时间的方法添加到每个属性的 development.log 中:

    module Flats
      class IndexSerializer < Api::V2::RealtyObjects::IndexSerializer
        attribute_list = %i[
          flat_number
          entrance_number
          floor_in_house
          live_area
          room_count
          total_area
        ]
        attributes(*attribute_list)
    
        def logger(name, value)
          Rails.logger.debug name, value, "#{Time.now.strftime('%M:%S--%N')}"
        end
    
        attribute_list.each do |attribute_name|
          define_method attribute_name do |value|
            logger(attribute_name, value)
            super
          end
        end
      end
    end
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-01-14
      • 2023-03-17
      • 2020-07-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-10-24
      • 1970-01-01
      相关资源
      最近更新 更多