9

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

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(甚至可能是一个 sproc)?

谢谢!

4

1 回答 1

3

有几件事跳出来。

首先,如果这段代码被调用 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)
于 2012-06-18T09:20:52.820 回答