2010-09-27 52 views
1

這是一個偏好,但我想知道人們認爲什麼是最佳選擇。我有一個問題,答案,以及點(因爲我需要跟蹤哪個用戶提出的觀點)數據庫表優化連接vs重複列

錶轉儲

Question: 
    id 
    title 

Answer: 
    id 
    question_id 
    user_id 
    response 

Point_Answer: 
    id 
    answer_id 
    user_id 
    points 

因此,在這種佈局得到最多的回答就需要一個複雜的連接順序。

SELECT t2.id, t2.user_id, t2.response, MAX(points) 
FROM Question as t1, 
    (SELECT qa.*, SUM(pa.points) as points 
    FROM answer as qa, Point_Answer as pa 
    WHERE qa.id = pa.answer_id 
    GROUP BY qa.id) as t2 
WHERE t1.id = %s AND t1.id = t2.question_id 

在哪裏,如果我改變這樣的:

Question: 
    id 
    title 

Answer: 
    id 
    question_id 
    user_id 
    response 
    points 

Point_Answer: 
    id 
    answer_id 
    user_id 
    points 

查詢就會少負擔

SELECT A.id, A.user_id, A.response, MAX(points) 
FROM Question as Q, Answer as A 
WHERE Q.id = %s AND Q.id = A.question_id 
GROUP BY A.id 

也意味着我必須確保當Point_Answer添加答案。點被添加。所以基本上是一個額外的更新。基本上它是「完整性與冗餘性」和一點優化,最好的方法是什麼?

回答

5

這將取決於第一個速度不是連接的複雜程度。單單這樣做會是一個非常糟糕的主意,因爲您不想編寫(一次)更復雜的查詢。表現是做這種事情的唯一真正理由。

如果第一個是不可接受的慢,那麼總結這些點的表或字段可以是一個可接受的非規範化,如果並且只有通過觸發器保持字段不是從應用程序更新(確保非規範化的準確性的唯一方法數)。您需要測試解決方案,包括額外的更新時間,以確定您是否確實節省了任何處理時間。這可能取決於數字改變的頻率。例如,如果您在更新時間中添加第二個並在select上節省了十秒,但是您爲每個selct 10,000次更新,這不是一個好的優化。但是,如果您製作報告的時間從一小時到幾毫秒,並且只爲插入或更新添加一毫秒,則可能是可以接受的。

沒有實際編碼和測試生產級別工作負載和數據的解決方案,沒有辦法回答這個問題。

+0

好吧,這是有道理的,它尚未在部署,但想知道什麼樣的最佳設計將是開始。我將與第一選擇一起去追求完整。如果我以後看到問題,我總是可以選擇第二個選項。 – Atherion 2010-09-27 20:09:04

1

如果查詢執行得相當好,我會保持原樣。一個醜陋的,表現良好的查詢在我的書中勝過冗餘。

使用冗餘選項,您需要確保將更新語句封裝在事務中以確保所有內容都得到更新;否則,您有可能導致數據不同步。

我曾與一些遺留應用程序進行冗餘路線沒有事務,並且當一個表不因任何原因而更新時,它變得混亂。

2

這取決於很多因素,其中大部分取決於您的設置。

最重要的兩個因素是:

  • 多久你正在運行的查詢。請記住,第二種解決方案不僅會佔用更多的磁盤空間(理論上可能會降低性能),還會要求您在添加記錄時處理非規範化結構。雖然這可以通過使用觸發器來自動執行(取決於RDBMS),但它仍然是性能開銷。
  • 您正在使用的RDBMS。你的第一個查詢可能很難看(我看到的情況更糟糕),但你確定它很慢嗎?獲得該問題明確答案的唯一方法是運行查詢並使用EXPLAIN [查詢]檢查RDBMS使用的查詢計劃。

所以基本上,我會堅持第一個解決方案。沒有規範化的關係方案有時候是件好事,但如果你確定的話,你應該對結構進行非規範化處理,如果你已經在類似生產環境中發現了應用程序的瓶頸,那麼它會提高性能。

+0

Thx克里斯幫助了很多。 – Atherion 2010-09-27 20:09:45