2010-11-08 61 views
10

我的問題是關於非規範化。在數據庫中,何時應該將派生數據存儲在自己的列中,而不是每次需要時計算它?在數據庫中,當你要存儲導出的數據?

例如,假設你有誰得到Upvotes提出的問題的用戶。您在其個人資料中顯示用戶的信譽。當用戶Upvoted,你應該增加自己的信譽,否則你應該計算它,當你找回自己的個人資料:

SELECT User.id, COUNT(*) AS reputation FROM User 
LEFT JOIN Question 
    ON Question.User_id = User.id 
LEFT JOIN Upvote 
    ON Upvote.Question_id = Question.id 
GROUP BY User.id 

處理器密集型如何進行查詢,以獲得用戶的口碑已經是這將是值得的前用自己的專欄逐步跟蹤它?

要繼續我們的例子,假設Upvote的權重取決於投射它的用戶有多少Upvotes(沒有多少聲望)。查詢其信譽突然爆炸:

SELECT 
    User.id AS User_id, 
    SUM(UpvoteWeight.weight) AS reputation 
FROM User 
LEFT JOIN Question 
    ON User.id = Question.User_id 
LEFT JOIN (
    SELECT 
    Upvote.Question_id, 
    COUNT(Upvote2.id)+1 AS weight 
    FROM Upvote 
    LEFT JOIN User 
    ON Upvote.User_id = User.id 
    LEFT JOIN Question 
    ON User.id = Question.User_id 
    LEFT JOIN Upvote AS Upvote2 
    ON 
     Question.id = Upvote2.Question_id 
     AND Upvote2.date < Upvote.date 
    GROUP BY Upvote.id 
) AS UpvoteWeight ON Question.id = UpvoteWeight.Question_id 
GROUP BY User.id 

這與增量式解決方案的難度大不相稱。正常化時將是值得的,和標準化的好處時,就失去了非規範化的利益(在這種情況下,查詢的難度和/或性能)?

回答

4

查詢獲取用戶聲譽的處理器密集程度如何,必須在它值得用它自己的列逐步跟蹤它?

這裏真的存在兩個問題:(1)這種改變是否會改善性能?(2)性能改進是否值得付出努力?


至於性能是否提高,這基本上是一個標準的利弊分析。

正常化的好處是基本上兩方面:

  • 更簡便的數據完整性

  • 與重新計算沒有問題(如果基礎數據的變化,所導出的列需要例如被重新-calculated)。

如果你蓋上有力實施的解決方案中的數據完整性(如觸發器,Sstored進程內,只能用直接撤銷表變化燙髮數據的變化,等...),那麼這成爲是否直接計算驗證源數據變化的成本是否保證導出的數據重新計算與每次重新計算派生數據。 (注意:保持數據完整性的另一種方法是強制按計劃重新計算派生數據,數據在某些時間容許範圍內可能不準確,StackExchange採用這種方法的一些數據)。

在一個典型的場景(更多的數據檢索和更少的底層數據更改)中,數學顯然偏向於保持表中的非規格化派生數據。

在底層數據發生變化的罕見情況下,經常不檢索派生數據,這樣做可能是有害的。現在


,我們到一個更重要的問題:將性能提升是值得的?

請注意,與所有的優化,最大的問題是「是優化甚至值得呢?」,因此是受兩個主要因素:

  1. 精確測量性能差異和一般性能分析。

  2. 在系統的大圖中進行此特定優化的上下文。

例如,如果查詢性能差異 - 必須首先測量時一如先前所述 - 在緩存的派生數據與計算的數據之間爲2%,則首先實現信譽緩存列時額外的系統複雜性可能不值得。但是關心與不關心的門檻是什麼,只要邊緣改善取決於應用程序的全貌。如果您可以採取措施在不同地點提高10%的查詢性能,請專注於2%。如果你是Google,額外2%的查詢性能需要花費20億美元額外硬件才能承擔,那麼無論如何都需要進行優化。

1

確實沒有明確的答案,因爲它取決於很多因素,比如網站的體積和頻率顯示的信譽(即僅在他們的個人資料頁面上或其每個用戶名的每個實例旁邊,無處不在)。唯一真正的答案是「何時變得太慢」;換句話說,你可能需要測試兩種情景並獲得一些真實世界的表演統計。

就我個人而言,我會在這種特殊情況下進行非規範化處理,並且在upvote表上具有插入觸發器,或者定期更新查詢來更新denromalized reputation列。是否真的是世界的盡頭有人的代表說「204」,而不是「205」,直到頁面刷新?

0

我只是想從另一個角度來看待DVK在上述響應中覆蓋的數據完整性問題。考慮其他系統是否需要訪問/計算派生數據 - 甚至像報告系統一樣簡單。如果其他系統需要使用派生值或更新upvote值,那麼您可能需要額外考慮如何重用計算代碼或如何確保派生值始終更新,而不管系統是否更改upvote。

相關問題