0

我有兩個活動記錄StudentDemographicsStudentWeeklyReport均具有has_many關係是這樣的:優化下面的代碼

class StudentDemographics < ActiveRecord::Base 
    has_many :student_weekly_reports, :foreign_key => :student_id 
end 

我要查馬克在最後的第五週研討會,最新一期每一個學生。如果結果是true,學生應該是積極的,否則不活躍。我有以下代碼。在這裏,我正在重複每個日期的循環。 @distinct是一組日期。

for i in [email protected] 
    active = 0 
    inactive = 0 
    sum = safe.length 
    @students = StudentDemographics.where("date <= ?", @distinct[i]).select("student_id") - safe 
    @students.each do |student| 
     @stu = StudentWeeklyReport.where(:student_id => student.student_id).select("student_id,golden_eggs").last(5) 
      if @stu.length > 4 
       if @stu[4].golden_eggs > @stu[0].golden_eggs 
        safe << student 
        active += 1 
       else 
        inactive += 1 
       end 
      else 
       safe << student 
       active += 1 
      end 
     end 
     @active[i] = active + sum 
     @inactive[i] = inactive 
end 

表現不好。它需要超過3秒的時間。我的mysql db在StudentWeeklyReports表中有13600個,在StudentDemographics表中有2000個。任何人都可以建議如何優化下面的代碼?

回答

1
 @students = StudentDemographics.includes(:student_weekly_reports) - safe 
for i in [email protected] 
    active = inactive = 0 
    @students.each do |student| 
     next if student.date > @distinct[i] 
     @stu = student.student_weekly_reports.select("golden_eggs").last(5) 
      if @stu.length > 4 && (@stu[4].golden_eggs <= @stu[0].golden_eggs) 
       inactive += 1 
      else 
       safe << student 
       active += 1 
      end 
     end 
     @active[i] = active + safe.length 
     @inactive[i] = inactive 
end 
+0

感謝您的幫助@Thaha KP。你的回答看起來不錯,但響應時間從3秒增加到12秒。它在控制檯日誌中打印一些說明命令。 – user2906085

+0

@ Thaha的解決方案看起來很好,與你發佈的循環相比,它不會變慢。 Thaha的解決方案肯定會更快。嘗試通過重新啓動服務器來運行這兩個循環,以查看兩者之間的實際差異。您的循環可能需要3秒,因爲ActiveRecord查詢緩存正在由內部執行。 –

+0

此外用&和'替換'&&也會有所幫助,因爲&&會檢查兩個條件,而'和'它不會檢查第二個條件,如果第一個條件爲false。 –

0
@students = StudentDemographics.includes(:student_weekly_reports).where("date <= ?", @distinct.min).select("student_id") 
# The above line will fetch all the necessary records you require 

for i in [email protected] 
active = inactive = 0 
@students = @student.select { |student_demographics| student_demographics.date <= @distinct[i] } - safe 
@students.each do |student| 
    @stu = student.student_weekly_reports.select("golden_eggs").last(5) 
    if @stu.length > 4 and (@stu[4].golden_eggs <= @stu[0].golden_eggs) 
    inactive += 1 
    else 
    safe << student 
    active += 1 
    end 
    end 
    @active[i] = active + safe.length 
    @inactive[i] = inactive 
end 
+0

@Amit ..在循環中,我們通過使用這個'student.student_weekly_reports'獲取與學生相關的每週報告。 。我們需要包含student_weekly_report和student_demographics ..?就像'StudentDemographics.includes(:student_weekly_reports).where(「date <=?」,@ distinct.min).select(「student_id」)' – user2906085

+0

嘗試編輯答案 –

+0

其實我們正在使用'eager_loading'這行' @students = StudentDemographics.includes(:student_weekly_reports).where(「date <=?」,@ distinct.min)'表示與每個StudentDemographics記錄關聯的所有'student_weekly_reports'都將被預取。所以,當我們正在執行'student.student_weekly_reports'時,將不會觸發任何查詢。你有什麼問題嗎? –