我有一個Sleep
模型,其實例一belongs_to
模型Person
的實例。我想將統計計算傳遞給後臺線程。人們自行報告他們的數據,可能會跳過一些日子。如何讓這組Rails 3.1查詢更高效?
我創建了一個Sleepstat
模型,並計劃計算每天的一些統計信息,其中有一個或多個Sleep
記錄的實例。但是,稍後人們可能會返回並編輯其數據,因此在此後臺任務中,我想掃描Sleepstat
的現有實例以確定needs_updating
標誌的狀態。
如果有人創建的某一天爲這沒有一個現有的Sleepstat
一個Sleep
記錄,那麼我希望後臺任務,以創建Sleepstat
和計算當天的統計數據。如果有人在已存在Sleepstat
的某一天添加了另一個Sleep
記錄,那麼我需要將Sleepstat
標記爲需要更新並使用新數據進行更新,以使統計數據保持最新。
我的想法是要做到以下幾點:
運行一個查詢返回所有
Sleep
記錄屬於有問題的Person
。對於這一點,我用這個查詢,因爲我希望它的工作原理:all_sleeps = Sleep.select('start_time,end_time,multiday,time_zone,in_progress').where(:person_id => self.id)
創建獨特
start_time
日期的數組:days_recorded = [] for sleep in all_sleeps days_recorded.push sleep.start_time.to_date end days_recorded = days_recorded.uniq
對於每個
days_recorded
的,看看是否存在Sleepstat
。如果沒有,請創建一個並計算統計信息。如果是,請檢查它是否爲needs_updating
。如果是這樣,計算統計。如果不是,則轉到days_recorded
中的下一個項目。days_recorded.each do |d| stat = Sleepstat.where(:date => d).first if stat.nil? # No record, so create one because we have data for that day and calculate stats ... else # There is a record. Evaluate whether it needs to be updated if stat.needs_updating? # Update the Sleepstat ... end end end
這種做法導致很多獨立的查詢:
Sleepstat Load (0.2ms) SELECT "sleepstats".* FROM "sleepstats" WHERE "sleepstats"."date" = '2011-12-10'
Sleepstat Load (0.2ms) SELECT "sleepstats".* FROM "sleepstats" WHERE "sleepstats"."date" = '2011-12-11'
Sleepstat Load (0.2ms) SELECT "sleepstats".* FROM "sleepstats" WHERE "sleepstats"."date" = '2011-12-12'
Sleepstat Load (0.2ms) SELECT "sleepstats".* FROM "sleepstats" WHERE "sleepstats"."date" = '2011-12-13'
我的想法是,試圖抓住所有的Sleepstat
S的第一,通過像查詢:
existing_stats = Sleepstat.where(:date => days_recorded)
然後在步驟3中遍歷它們。我的嘗試如下所示:
existing_stats = Sleepstat.where(:date => days_recorded)
days_recorded.each do |d|
stat = existing_stats.where(:date => d)
if stat.nil? || stat.length == 0
# No record, so create one because we have data for that day and calculate stats
...
else
# There is a record. Evaluate whether it needs to be updated
if stat.needs_updating?
# Update the Sleepstat
...
end
end
end
這只是導致了很多更復雜的個人查詢:
Sleepstat Load (0.5ms) SELECT "sleepstats".* FROM "sleepstats" WHERE "sleepstats"."date" IN ('2011-12-07', '2011-12-06', '2011-12-08', '2011-12-09', '2011-12-10', '2011-12-11', '2011-12-12', '2011-12-13', '2011-12-14', '2011-12-15') AND "sleepstats"."date" = '2011-12-10'
Sleepstat Load (0.9ms) SELECT "sleepstats".* FROM "sleepstats" WHERE "sleepstats"."date" IN ('2011-12-07', '2011-12-06', '2011-12-08', '2011-12-09', '2011-12-10', '2011-12-11', '2011-12-12', '2011-12-13', '2011-12-14', '2011-12-15') AND "sleepstats"."date" = '2011-12-11'
Sleepstat Load (0.6ms) SELECT "sleepstats".* FROM "sleepstats" WHERE "sleepstats"."date" IN ('2011-12-07', '2011-12-06', '2011-12-08', '2011-12-09', '2011-12-10', '2011-12-11', '2011-12-12', '2011-12-13', '2011-12-14', '2011-12-15') AND "sleepstats"."date" = '2011-12-12'
Sleepstat Load (0.4ms) SELECT "sleepstats".* FROM "sleepstats" WHERE "sleepstats"."date" IN ('2011-12-07', '2011-12-06', '2011-12-08', '2011-12-09', '2011-12-10', '2011-12-11', '2011-12-12', '2011-12-13', '2011-12-14', '2011-12-15') AND "sleepstats"."date" = '2011-12-13'
我怎樣才能提高這一過程的效率,使我沒有命中數據庫這麼多次?
關於`sleeps = Sleep.where(date:date) `...`睡眠`有字段`start_time`,我正在使用它來評估日期,所以我需要將它從時間戳轉換爲日期。但是,它存儲在UTC中。我如何將它投射到日期並保留時區信息? ('person_id =?AND CAST(start_time AS DATE)=?',self.id,the_date)`(ps使用Postgres ) – Clay 2011-12-16 18:10:58