【问题标题】:ActiveRecord query much slower than straight SQL?ActiveRecord 查询比直接 SQL 慢得多?
【发布时间】:2012-06-20 05:48:21
【问题描述】:

我一直致力于优化我项目的数据库调用,我注意到以下两个相同调用之间的性能存在“显着”差异:

connection = ActiveRecord::Base.connection()
pgresult = connection.execute(
  "SELECT SUM(my_column)
   FROM table
   WHERE id = #{id} 
   AND created_at BETWEEN '#{lower}' and '#{upper}'")

第二个版本:

sum = Table.
      where(:id => id, :created_at => lower..upper).
      sum(:my_column)

使用第一个版本的方法平均需要 300ms 执行(该操作在其中总共调用了几千次),使用第二个版本的方法大约需要 550ms。速度几乎下降了 100%。

我仔细检查了第二个版本生成的 SQL,它与第一个版本相同,只是它在表列前加上表名。

  • 为什么会变慢? ActiveRecord 和 SQL 之间的转换真的使操作花费了将近 2 倍吗?
  • 如果我需要多次执行相同的操作并且不想承受开销,我是否需要坚持直接编写 SQL(甚至可能是存储过程)?

谢谢!

【问题讨论】:

  • 只需使用 .explain 并查看生成的查询,我确信它看起来不同,这就是为什么它需要更长的时间
  • 我仔细检查了查询计划,它们都是相同的,成本和所有。在第二个版本中,必须从 .sum 中替换 .select,因为您从那个版本中得到了一个 Fixnum,而我找不到对用于生成它的查询进行 .explain 的方法。

标签: ruby-on-rails ruby-on-rails-3 postgresql database-performance


【解决方案1】:

有几件事跳出来了。

首先,如果这段代码被调用了 2000 次并且需要额外的 250 毫秒来运行,那么每次调用将 Arel 转换为 SQL 大约需要 0.125 毫秒,这并非不现实。

其次,我不确定 Ruby 中 Range 的内部结构,但lower..upper 可能会进行范围大小等计算,这将对性能造成很大影响。

您是否看到以下相同的性能受到影响?

sum = Table.
      where(:id => id).
      where(:created_at => "BETWEEN ? and ?", lower, upper).
      sum(:my_column)

【讨论】:

  • 据我了解, .. 只是 ActiveRecord 转换为 BETWEEN 语句的语法糖,如果它确定操作数是 Time 对象。我尝试了那个版本,并不断得到与慢版本相同的确切数字。基本上,这听起来确实像是转换占用了时间。我将对其进行分析以获得更多粒度。
  • 是的,它仍然必须生成一个它传入的 Range 对象,但我想它不会做任何艰苦的工作,因为没有生成迭代器。 AR 是否可以在对每个项目求和之前为每个项目制作对象?这可能会减慢它的速度。不过似乎不太可能。
  • 基于分析,第一个版本直接跳转到执行查询。然而,第二个版本在 30 层深度的各种 AR 魔法堆栈上花费了大约 35% 的额外执行时间。版本较慢的版本可以看这里:pastebin.com/bipTy3c5 直接SQL版本在这里:pastebin.com/LysaGUTy
  • 请注意,性能爱好者应该在这里做什么?每当我真的需要收紧事情时,我是否要进行手动查询?是否有更系统的方法(可能是宝石或其他我可以大量应用的东西),或者这一切都将根据需要进行,例如手动重写所有胖循环?
  • 您没有提及您使用的是哪个数据库,但“准备好的声明”可能是一个更好的选择;但要非常小心,因为我大量使用的 postgesql 有时可能会因为在随后调用准备好的语句时不重新评估查询计划而对此感到头疼。这里有一个重要的讨论:patshaughnessy.net/2011/10/22/…。总的来说,如果我要执行相同的查询 2000 次,我倾向于将查询作为存储过程移动到数据库中,然后调用它。 YMMV。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-12-10
  • 2023-03-14
  • 2011-09-20
  • 2021-11-13
相关资源
最近更新 更多