2009-01-17 27 views
9

我試圖找到如下問題的最佳解決方案:有必要設計一個數據庫(Postgres的爲主),在它的觸發器和計數器的系統,將形成一個有效查詢,更新和存儲「每篇文章中存在多少未讀評論(或博客文章,或者相似)」信息的系統,這些信息會顯示在頁面上。實施的「未讀的意見」的高效系統專櫃

這涉及到頭部的每個解決方案,有一些嚴重的缺點,無論是在查詢或存儲,或更新部件。即它需要太多的存儲空間,或者需要太多的更新,或者太昂貴的查詢。

你的expirience怎麼樣?也許這種問題已經形成了一個很好的解決方案?

回答

8

我會保持模式儘可能簡單,所以查詢將盡可能簡單。這通常也具有最低的存儲要求。當然,設置索引來支持這個查詢。

下一步:測量性能! 「要衡量就是知道。」什麼是響應時間?服務器上的負載是多少?只要性能可以接受,保持架構和查詢簡單。如果不是絕對必要的,不要犧牲可維護性:您的後繼者將在稍後感謝您。

如果性能確實是一個問題,看看你正在使用你的應用程序框架的緩存功能。不執行查詢始終比執行優化更快。

4

如果你真的不你的資源包線內取得成功,也許你必須調整用戶體驗。也許存儲上次訪問線程的日期就足夠了。

4

我不認爲典型的,規範化的方法會給你帶來低效的查詢。假設你有一個表article_comments與PK (article_id, comment_id)和另一個表comments_seen_by_user與PK (user_id, article_id, comment_id)。所有你需要做的是,在頁面上列出的每個文章:

SELECT count(*) FROM article_comments ac 
WHERE article_id = ?    -- Parameter 
AND NOT EXISTS (
    SELECT 1 FROM comments_seen_by_user csbu 
    WHERE csbu.user_id = ?   -- Parameter 
    AND csbu.article_id = ac.article_id 
    AND csbu.comment_id = ac.comment_id 
) 

如果顯示在頁面上20篇文章,你會碰到上面的查詢20次,每次運行時會使用索引來拉從article_comments中說出10-20行,而子查詢測試只是comments_seen_by_user上的另一個索引掃描,因此總的來說,可能需要20 *(20 * 2)= 800索引查找才能顯示給定頁面。這對於現代數據庫來說並不算什麼。我可能忽視了PostgreSQL可能找到的更好的查詢計劃。

你有沒有試過這個,並發現性能要?如果是這樣,我的第一個猜測是你有一段時間沒有編輯VACUUM。否則,我必須得到我對每頁文章數量或每篇文章的評論的估計,這是錯誤的 - 請在此情況下更新詳細信息。

1

我第二j_random_hacker的答案,只有我會避免存放在comments_seen_by_user表中的article_id因爲COMMENT_ID應爲每個評論全球唯一的。另外,PostgreSQL中的3維(以及更小程度的2-d)索引仍然很慢,所以儘量避免它們。

有周圍的user_id表上沒有真正的好辦法,COMMENT_ID值來存儲信息有關閱讀評論,只是確保它具有唯一索引。對於PostgreSQL,這樣的表中幾千萬行根本沒有問題,只要它可以將索引保存在內存中即可。您可以跟蹤該指數的大小(在磁盤上8KB頁數)與查詢的系統表:

select relname,relpages from pg_class where relname='comments_seen_by_user_pkey'; 
+1

同意的,全球唯一的comment_ids是一個好主意。 – 2009-01-17 13:39:15

0

我會同意去歸一化的方法,看看它的作品出來。通常我應該。但是,您也可以在'comment'表上使用一些INSERT觸發器,它會更新基礎(即文章)表中的註釋計數器。它取決於本網站的使用情況:如果評論大部分是閱讀的(與添加評論相比),基於觸發的方法的開銷應迅速攤銷。如果它是一個具有較高評論負載的網站,則可能會導致性能下降。

我會尋找一個簡單的,規範化的表結構,並在稍後添加其他優化,當你有一些合理的使用情況。

+0

因爲每個用戶的評論觀看歷史是獨立的,所以您的觸發器需要將表中的nUsers行更新爲(user_id,article_id)(或一些變體)作爲其PK。儘管如此,仍然可行。 – 2009-01-17 13:43:01