2012-04-30 2 views
4

Rails 3.1、Ruby 1.9.2、AR/MySQL。1日あたり多くのレコードのうち1つだけがレールに保持されます。最後に保持する、残りを削除する

同じタイプの結果にその期間中に多くの結果がある場合は、期間(日)ごとに1つの結果のみを保存する方法に関する提案を探しています。たとえば、株価を追跡する例があります。当初は15分ごとに価格を保存していましたが、1つの価格帯ごとに1週間しか保管する必要はありませんでした。最初の1週間後には、1日あたり1つの価格(最終レコード、終値)が必要になります。ここで

は、作業を行う簡単な最初の試みですが、ひどく非効率的である:任意のヘルプ/提案を事前に

# stock has many prices, price has one stock 
# get all prices for single stock older than 1 week 
prices = stock.prices.where("created_at < ? ", Time.now-1.week) 
prices.group_by{ |price| price.created_at.to_date }.each do |k,v| # group by day 
    if v.count > 1 # if many price points that day 
    (v[0]..v[v.size-2]).each {|r| r.delete} # delete all but last record in day 
    end 
end 

感謝。私はそれが誰かを助けることを望んでそれを通って作業するように更新しようとします。

答えて

1

代わりDELETE_ALLを行い

(v[0]..v[v.size-2]).each {|r| r.delete} 

のようにそれぞれの上に、削除ではなく、私はこれをやったことがないが、私はかなり確信している最後のもの

price_ids_to_keep = [] 
if v.count > 1 # if many price points that day 
    price_ids_to_keep << v[-1].id # get the last 
else 
    price_ids_to_keep << v[0].id 
end 

prices.where('id not in (?)',price_ids_to_keep).delete_all 

はそれが


動作するはずの呼び出しの

これはDELETEクエリが少なくなるため、これが優れていますが、これをすべてjにする方法があるはずです1つの大きな質問があります


ビジネスの目で、あなたまたはあなたのチームはそれについてよりよく考えるべきです。今日のストレージは安価であり、このような情報は、将来のデータマイニングなどのために貴重なものになる可能性があります。

3

これをSQLですべて実行し、範囲を最後に実行した時間に制限することで、より効率的にすることができます。また、古い終日のエントリを「アーカイブ済み」としてマークする列を追加すると、クエリがより簡単になります。アーカイブ価格は、1週間後に削除しない価格です。

rails generate migration add_archived_to_prices archived:boolean 

移行する前に、created_at列のインデックスへの移行を変更してください。 、最後の注意として、

# Find the last entry for each day for each stock using SQL (more efficient than finding these in Ruby) 
keepers = 
    Price.group('stock_id, DATE(created_at)'). 
     having('created_at = MAX(created_at)'). 
     select(:id). 
     where('created_at > ?', last_run) # Keep track of the last run time to speed up subsequent runs 

# Mark them as archived 
Price.where('id IN (?)', keepers.map(&:id)).update_all(:archived => true) 

# Delete everything but archived prices that are older than a week 
Price.where('archived != ?', true). 
     where('created_at < ?", Time.now - 1.week). 
     where('created_at > ?', last_run). # Keep track of the last run time to speed up subsequent runs 
     delete_all 

group()update_all()を結合しないようにしてください:

class AddArchivedToPrices < ActiveRecord::Migration 
    def self.up 
    add_column :prices, :archived, :boolean 
    add_index :prices, :created_at 
    end 

    def self.down 
    remove_index :prices, :created_at 
    remove_column :prices, :archived 
    end 
end 

ワークフローは、このような何かを行くだろう。 group()update_all()で無視されます。

関連する問題