2009-03-04 81 views
4

我正在一個簡單的標準化數據庫的網站上工作。總數應該是非規範化的嗎?

有一個名爲Pages的表和一個名爲Views的表。每次查看頁面時,該視圖的唯一記錄都會記錄在視圖表中。

當在網站上顯示一個頁面時,我使用一個簡單的MySQL COUNT()來累計顯示的視圖數量。

數據庫設計看起來很好,除了這個問題:我在如何檢索數千人中瀏覽量最高的10個頁面時感到不知所措。

我是否應該通過添加Pages.views列來保持每個頁面的總視圖數量來對Pages表格進行非規範化處理?或者有沒有一種有效的方式來查詢前10個最常瀏覽的頁面?

回答

8
SELECT p.pageid, count(*) as viewcount FROM 
    pages p 
    inner join views v on p.pageid = v.pageid 
    group by p.pageid 
    order by count(*) desc 
    LIMIT 10 OFFSET 0; 

我無法測試這個,但沿着這些線。除非由於性能限制(我剛剛學習術語「過早優化」,而且如果您這樣做似乎適用),否則我不會存儲該值。

+1

+1表示在性能問題出現之前不存儲總數。 – Thilo 2009-03-04 04:40:59

1

我可能會在Pages表中包含views列。

這似乎是一個完全合理的正常化突破給我。特別是因爲我無法想象你刪除視圖,所以你不會指望計數失控。在這種情況下,參照完整性似乎不是超關鍵。

1

數據庫規範化是關於存儲數據的最有效/最不重複的方式。這對於事務處理很有用,但通常直接與需要有效地再次獲取數據的衝突。這個問題通常通過派生表(索引,物化視圖,彙總表......)來解決,並且具有更易於訪問的預處理數據。這裏(稍微過時)的流行語是數據倉庫。

我認爲你想保持你的頁表正常化,但有一個額外的表與總數。根據這些計數的最新數據,您可以在更新原始表格時更新表格,也可以讓後臺作業定期重新計算總計。

只有在真正遇到性能問題時纔會這樣做,除非擁有大量的記錄或大量的併發訪問,否則不會這樣做。保持你的代碼的靈活性,以便能夠在表格和不具有表格之間切換。

0

在這種情況下非規範化肯定會起作用。你的損失是額外的柱子用完的額外的儲藏室。

或者,您可以設置一項計劃作業,以在夜間基礎上填充此信息,只要您的流量低,x時間段。

在這種情況下,除非手動運行此查詢,否則您將失去立即知道頁面計數的能力。

反規範化肯定可以用來提高性能。

--Kris

+0

損失既是額外的列,也是需要保持一致。我同意在這種情況下這是合理的。 – thomasrutter 2009-03-04 04:43:08

3

它依賴於信息化水平,你正試圖保持。如果你想記錄誰看過什麼時候?然後單獨的表格很好。否則,視圖列是要走的路。另外,如果您保留一個單獨的列,您會發現該表會更頻繁地鎖定,因爲每個頁面視圖都會嘗試更新相應行的列。

Select pageid, Count(*) as countCol from Views 
group by pageid order by countCol DESC 
LIMIT 10 OFFSET 0;