2011-01-20 38 views
2

我建立一個投票系統,由此每個投票與UserID一個投票表捕獲及表決與任或-1一個int沿着DateTime表決系統:我應該使用SQL觸發器還是更多代碼?

我還保持運行總計TotalVotes中包含用戶實際表決的項目表。這種方式我不會經常運行一個查詢到SUM投票表。

當涉及到更新TotalVotes字段時,我的問題是一種利弊問題。關於代碼可管理性,在應用程序中添加更多更新方法可以輕鬆排除故障並發現任何潛在問題。但是,如果此應用程序在其用戶羣中顯着增長,則可能會導致從應用程序到數據庫的大量額外SQL調用。可以這麼說,使用觸發器可以保持「全部在sql系列中」,並且應該增加一點性能提升,並且保持代碼基礎以外的平凡活動。

我明白,過早的優化可以在這個特定的問題被調用,但因爲我還沒有建立它,我不妨試着找出更好的辦法出了大門的。

我個人傾向於觸發器。請給我你的想法/推理。

+1

您是否確定'SUM投票表'實際上超出了您的預算? – 2011-01-20 18:04:39

回答

1

我已經完成了多年的觸發方法,並且總是很開心。所以,正如他們所說的,「進來吧,水很好。」不過,我通常在涉及很多桌子時做,而不僅僅是一桌。

優點/缺點是衆所周知的。實現這個價值是一個「現在付錢給我」的決定,你在插入上多付一點錢以獲得更快的讀取。當且僅當您想要以5毫秒而不是500毫秒讀取時,這是要走的路。

PRO:TotalVotes總是立即可用一次閱讀。

PRO:您不必擔心代碼路徑,使插入的代碼更加簡單。在大型應用程序中乘以許多表格,這對可維護性來說是一件大事。對於每個INSERT,您還需要額外支付更新費用。在你注意到這個之前,比大多數人想象的要多得多。

CON:對於許多表格,手動編碼觸發器可能會變得棘手。我推薦一個代碼生成器,但是由於我寫了我所知道的唯一一個代碼生成器,所以我會進入自我推銷領域。如果你只有一個表,只需手動編碼即可。

CON:爲確保完整的正確性,應該不可能從控制檯或代碼發出更新來修改TotalVotes。這意味着它更復雜。觸發器應作爲通常不使用的特殊超級用戶執行。父表上的第二個觸發器觸發UPDATE,並阻止對TotalVotes的更改,除非進行更新的用戶是特殊的超級用戶。

希望這給你足夠的決定權。

1

我的第一直覺是寫一個UDF執行SUM操作,使TotalVotes基於該UDF計算列。

+0

+1我想我將不得不研究UDF並找出如何做到這一點:-s – 2011-01-20 18:10:39

2

我建議你建立一個存儲過程,既執行投票插入,又對總票數進行更新。然後你的應用程序只需要知道如何記錄投票,但是當你調用它的時候,關於它究竟發生了什麼的邏輯仍然包含在一個地方(存儲過程,而不是特定的更新查詢和單獨的觸發器) 。

這也意味着,以後如果要刪除的更新,以總票數,你必須改變是通過註釋掉更新一部分的過程。

+0

+1感謝你。我意識到SP有自己的位置,這絕對可以成爲其中的一員,但在我的具體應用中,我不惜一切代價避免了SP。 – 2011-01-20 18:11:46

+0

啊。在這種情況下,觸發器當然是一個可行的選擇。 :)該字段上的索引可能會使SUM()速度足夠快以抵消性能問題,而不需要一個。 – Tridus 2011-01-20 18:23:44

2

不成熟的過早優化將總數保存在一個表中,而不是根據需要對數據進行求和。你真的需要對數據進行非規範化以獲得性能嗎?

如果您不需要對數據進行非規格化,那麼您不需要編寫觸發器。

+0

投票表將增長到幾十甚至幾十萬條記錄,總投票數將顯示在幾乎每一頁上。是的,我需要優化它,而不是每次總結它。 – 2011-01-20 18:14:36

+0

@rockinthesixstring:在嘗試之前不要敲它。我會建議創建一個表格並生成假數據,然後分析建議的解決方案的性能。 – 2011-01-20 20:09:52

3

另一種選擇是在投票表上創建視圖,將投票合計爲TotalVotes。 然後索引視圖。

SQL Server優化器(我認爲只有企業版)的神奇之處在於,當它看到sum(voteColumn)的查詢時,它會從相同數據視圖的索引中選擇該值,當您考慮你不是直接在查詢中引用視圖!

如果沒有企業版可以查詢的視圖,而不是表中的總票數,然後走索引的優勢。

索引實質上是優化器意識到的數據的非規範化。您可以根據需要創建或刪除它們,並讓優化器找出它(無需更改代碼)。一旦您開始制定自己手工製作的非規範化的路徑,您將在未來幾年內將其融入代碼中。

退房Improving performance with indexed views

有必須滿足獲得工作索引視圖一些具體的標準。下面是根據你的數據模型的猜測樣本:

create database indexdemo 
go 
create table votes(id int identity primary key, ItemToVoteOn int, vote int not null) 
go 

CREATE VIEW dbo.VoteCount WITH SCHEMABINDING AS 
select ItemToVoteOn, SUM(vote) as TotalVotes, COUNT_BIG(*) as CountOfVotes from dbo.votes group by ItemToVoteOn 
go 
CREATE UNIQUE CLUSTERED INDEX VoteCount_IndexedView ON dbo.VoteCount(itemtovoteon) 
go 
insert into votes values(1,1) 
insert into votes values(1,1) 
insert into votes values(2,1) 
insert into votes values(2,1) 
insert into votes values(2,1) 
go 

select ItemToVoteOn, SUM(vote) as TotalVotes from dbo.votes group by ItemToVoteOn 

而這個查詢(不引用視圖或擴展它的指數)在此執行計劃的結果。注意使用索引。當然,刪除索引,(並且提升插入性能)

alt text

而且一個硬道理。在你啓動和運行之前,如果任何類型的非規範化實際上會幫助整體吞吐量,那麼你就會知道這種方法。通過使用索引您可以創建它們,測量它是否有幫助或傷害,然後根據需要保留或刪除它們。這是唯一可以安全執行的非規範化性能。

相關問題