私は一日中クエリをリファクタリングしようとしていました。20レコードのテーブルがロードされるまでに数分かかりました。最初に、私はこのstackoverflowの投稿でクエリを非難しました:
rails-Rails.cacheを使用するとエラーが発生します
ただし、いくつかのテストを行った後、クエリの読み込みが非常に速く、原因ではないことに気付きました。
次に、この投稿で説明したように、カミナリが何千ものレコードをルビーオブジェクトに入力していると思ったので、カミナリのせいにしました。
しかし、それも間違っていました。カミナリは一度に20レコードしかロードしていませんでした(ロガーを使用して、ロードされているレポートの数を確認しましたが、20が表示されました)。
だからついに私は本当の犯人を見つけたと思います。これは、そのページのページネーション中に発生する別のクエリです。このクエリを実行するたびに、読み込みに20秒以上かかることに気付きました。
def virtual_fence_duration
inside_fence_time = nil
outside_fence_time = nil
outside_fence_time = self.time
previous_reports = Report.where{(time < my{self.time}) &
(unit_id == my{self.unit_id})}.order('time desc')
previous_reports.each do |report|
alerts = report.alerts.collect { |a| a.code_name }
if alerts.include? "Inside virtual fence"
inside_fence_time = report.time
break
end
end
if inside_fence_time && outside_fence_time
"Virtual Fence Elapsed Time: #{(((outside_fence_time - inside_fence_time).to_i).to_f/60.0).ceil} minutes"
else
""
end
end
基本的に、このメソッドは、「仮想フェンスの外側」にあるアラートがある場合に呼び出されます。時間を保存します。次に、その前のすべてのレポートをクエリします(レポートhas_manyアラート)。次に、rubyの各イテレーターを使用してすべてのレポートを調べ、次にそれらのレポートに関連付けられたアラートを使用して、「仮想フェンスの内側」にあるアラートを見つけます。次に、そのレポートの時間を保存し、2つの時間の差を取ります。2つの期間の間に多くのレポートがある場合、このロジックは永遠にかかるようです。sql(mysql)またはrubyでこれを行うためのより効率的な方法はありますか?