私はSleep
モデルを持っています。インスタンスはbelongs_to
で、Person
モデルのインスタンスです。統計の計算をバックグラウンドスレッドに渡したい。人々は自分のデータを自己報告し、数日をスキップすることがあります。Rails 3.1のクエリをより効率的にするにはどうすればよいですか?
私はSleepstat
モデルを作成し、Sleep
の1つ以上の記録されたインスタンスがある毎日の統計を計算する予定です。しかし、このバックグラウンドタスクでは、Sleepstat
という既存のインスタンスをスキャンして、needs_updating
フラグのステータスを調べる必要があります。
誰かがSleepstat
が存在しない日にSleep
レコードを作成した場合、バックグラウンドタスクでSleepstat
を作成し、その日の統計を計算します。もし誰かがのある日に追加のSleep
レコードを追加した場合は、最新の統計情報を最新の状態に保つために、必要に応じてSleepstat
にフラグを立てて、新しいデータで更新します。
が質問に
Person
に属するすべてのSleep
レコードを返すために、クエリを実行します。私の考えは次の操作を実行することでした。 、
days_recorded
のそれぞれについてdays_recorded = [] for sleep in all_sleeps days_recorded.push sleep.start_time.to_date end days_recorded = days_recorded.uniq
かどうかを確認します:
all_sleeps = Sleep.select('start_time,end_time,multiday,time_zone,in_progress').where(:person_id => self.id)
がユニーク
start_time
日付の配列を作成します。そのために、私は私が期待するように動作し、このクエリを使用しました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
このアプローチは、独立したクエリの多くにつながる:
existing_stats = Sleepstat.where(:date => days_recorded)
:
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
秒のすべてをつかむしようとしました
と入力し、手順3で繰り返します。私の試行は次のようになります。
私は何度データベースを打っていないよよう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'
がどのように私は、このプロセスの効率を向上させることができます:
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
これは単に、より複雑な個々のクエリの多くにつながりましたか?
「sleeps = Sleep.where(date:date)」に関する質問は、arel tablesを見てください。これにより、レコードのインスタンシエーションをスキップして必要なデータのみを読み込むことができます。 '...' Sleep'は、私が日付を評価するために使用しているフィールド 'start_time'を持っていますので、タイムスタンプから日付にキャストする必要があります。しかし、それはUTCに保存されています。どのように日付にキャストし、タイムゾーン情報を保持することができますか? self_id、the_date) '(ps)を使用しています。(sleep_on_date = Sleep.select( 'start_time、end_time、multi_day、time_zone、in_progress' ) – Clay
mmmm。時間を扱うことは常に難しい(btw、間違いのために申し訳ありません)。特に、サイトの日付/時刻を入力すると、指定した時刻がタイムゾーンにあると予想されるためです。クライアントのタイムゾーンを検出してフィールドをUTCに変換し、おそらくクライアントのタイムゾーンを検出してそれを元に戻すことをお勧めします。一方で、それは過ちかもしれません...デートのために。何人の人が、別のタイムゾーンで日付+ 1と効果的に一致するDateTimeを入力しますか? –
あなたの問題は夜を中心に集中しています。あなたはすでに、「睡眠」が人々が眠ったと感じる日にリンクされることを選択しました。これは設計上の問題です...すべてのことを切り上げました。あなたの日付を3つの整数列(日、月、年)にインデックスを付けて保存してみませんか?あなたがパフォーマンスを求めているなら、それは私が考える方法です –