2013-06-03 74 views
1

我的數據庫中有一個「投票」表,每天都在增長,目前大約有1億行。對於內部分析/見解,我曾經有一個rake任務,它將計算一些基本指標,比如過去幾天每天進行的投票數量。這只是一個COUNT,在「created_at」日期有一個where子句。在Rails/PostgreSQL的大表上做分析

這個rake任務做得很好,直到我刪除了「created_at」上的索引,因爲它似乎對所有其他不需要此索引的面向用戶的查詢的應用性能有負面影響,特別是當插入一個新行。

目前我對我的應用程序和此表中發生的事情沒有太多見解。不過,我真的不想在如此大的表格上添加索引,如果它僅用於我自己的用途。

我還能試試嗎?

+0

這裏有什麼問題? – Substantial

+1

@gg_s查詢在這張桌子上執行「計數」並帶有日期條件永久或不工作 – Emmanuel

回答

0

這只是一個COUNT,在「created_at」日期有一個where子句。

在這種情況下,你可以使用的唯一可靠的指標是created_at一...

如果寫入性能是一個問題(記錯它不可能...)和您使用的是複合主鍵,使用該索引對錶進行聚類也可能有所幫助。

1

或者,您可以完全避開Vote表並保留一個外部帳簿。

每次投票時,都會調用一個單獨的理貨類,以保持投票的投票數。每天會有一個理貨記錄。統計記錄將有一個整數,表示當天投票的數量。

對Tally類的每個增量調用將查找當前日期(今天)的計數記錄,增加投票計數並保存記錄。如果沒有記錄存在,則會創建一個並相應地增加。

例如,讓我們有一個名爲VoteTally的類,它具有兩個屬性:日期(日期)和投票計數(整數),沒有時間戳,沒有關聯。這裏的模式將是什麼樣子:

class VoteTally < ActiveRecord::Base 

    def self.tally_up! 
    find_or_create_by_date(Date.today).increment!(:votes) 
    end 

    def self.tally_down! 
    find_or_create_by_date(Date.today).decrement!(:votes) 
    end 

    def self.votes_on(date) 
    find_by_date(date).votes 
    end 

end 

然後,在Vote模式:

class Vote < ActiveRecord::Base 
    after_create :tally_up 
    after_destroy :tally_down 

    # ... 

    private 

    def tally_up ; VoteTally.tally_up! ; end 
    def tally_down ; VoteTally.tally_down! ; end 

end 

這些方法將獲得投票數:

VoteTally.votes_on Date.today 
VoteTally.votes_on Date.yesterday 
VoteTally.votes_on 3.days.ago 
VoteTally.votes_on Date.parse("5/28/13") 

當然,這是一個簡單的例如,你將不得不適應它來適應。這將在投票時導致額外的查詢,但它比沒有索引的100M記錄上的where子句要快得多。這個解決方案可能有些微不準確,但我認爲這是可以接受的,因爲每日投票計數的軼事性質。

0

如果指數有真正的寫性能產生影響,這是現在,然後運行統計中只有少數人,你可能會考慮另一種通用的方法:

你可以從你分開你的「事務處理數據庫」你的「報告數據庫」。

您可以定期更新您的報告數據庫,並僅在此處創建僅限報告的索引。有關報告的更多查詢不會與面向事務的流量發生衝突,並且它們運行多長時間無關緊要。

當然,這增加了一定的延遲,並增加了系統的複雜性。另一方面,如果您定期滾動報告數據庫,則可以確保您的備份方案真正有效。