次のクエリはかなり高速に実行されますが、後で実行する必要のある一連の処理により、このメソッドの速度が大幅に低下します。私はリファクタリングにいくつかの助けを使うことができました。
def self.sum_amount_chart_series(start_time)
orders_by_day = Widget.archived.not_void.
where(:print_datetime => start_time.beginning_of_day..Time.zone.now.end_of_day).
group(pg_print_date_group).
select("#{pg_print_date_group} as print_date, sum(amount) as total_amount")
# THIS IS WHAT IS SLOWING THE METHOD DOWN!
(start_time.to_date..Date.today).map do |date|
order = orders_by_day.detect { |order| order.print_date.to_date == date }
order && order.total_amount.to_f.round(2) || 0.0
end
end
def self.pg_print_date_group
"CAST((print_datetime + interval '#{tz_offset_hours} hours') AS date)"
end
私はこのメソッドのベンチマークを行いました。問題のあるコードは、一連の日付を生成し、各日付の量を含む新しい配列をマップする一連のループです。このようにして、金額の有無に関係なく、すべての日付の金額を含むシリーズを取得します。
クエリが数個の日付のみを返す場合、かなり高速に実行されます。ただし、開始日を1〜2年前に戻すと、非常に遅くなります。本当の犯罪者は.detectメソッドです。activerecordオブジェクトの配列をスキャンするのは非常に遅いです。
このシリーズを生成するためのより高速な方法はありますか?