9

プロジェクトのDB呼び出しの最適化に取り組んでいますが、以下の2つの同一の呼び出しのパフォーマンスに「大幅な」違いがあることに気付きました。

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

および2番目のバージョン:

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

最初のバージョンを使用する方法は、実行に平均300msかかり(操作はその中で合計で数千回呼び出されます)、2番目のバージョンを使用する方法は約550msかかります。これは、速度がほぼ100%低下します。

2番目のバージョンで生成された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 に答える