2010-09-10 58 views
10

我和我的朋友正在建立一個網站,並有重大分歧。該網站的核心是一個關於「人」的評論數據庫。基本上人們可以輸入評論,他們可以輸入評論的人。然後觀衆可以在數據庫中搜索評論中的單詞或人名的部分內容。它完全由用戶生成。例如,如果有人想發表對某人姓名的拼寫錯誤版本的評論,他們可以,而且沒關係。因此,可能會有多個不同人物的拼寫被列爲幾個不同的條目(一些中間名,一些暱稱,一些拼寫錯誤等),但這一切都可以。我們不在乎人們是否對隨機的人或想象中的人發表評論。不必要的標準化

無論如何,問題是關於我們如何構建數據庫。現在,它只是一個表註釋ID作爲主鍵,再有就是對「人」的註釋字段約爲:

評論ID - 評論 - 人

1 - 「他很奇怪」 - 約翰·史密斯

2 - 「臭丫頭」 - 珍妮

3 - 「同性戀」 - 約翰·史密斯

4 - 「欠我$ 20」 - Jennyyyyyyyyy

一切工作正常。使用數據庫,我可以創建列出特定「人員」的所有「評論」的頁面。但是,他着迷於數據庫沒有正常化。我讀了正常化,並瞭解到他錯了。表格IS目前已經規範化,因爲評論ID是唯一的並且決定了'評論'和'人員'。現在他堅持認爲'人'應該擁有自己的桌子,因爲這是'事情'。我不認爲這是必要的,因爲即使'人'真的是更大的容器(一個'人'可以對他們有很多'評論'),數據庫似乎運行得很好,'人'是屬性評論ID。我針對不同的SQL選擇使用了各種PHP調用,使其在輸出中以神奇的方式顯得更加複雜,用戶可以通過不同的方式搜索並查看結果,但實際上,安裝非常簡單。我現在讓用戶用豎起大拇指向下排列評論,並在同一張桌子上保留一個「分數」作爲另一個字段。

我覺得目前沒有必要爲獨特的「人物」條目設置單獨的表格,因爲「人物」沒有自己的「分數」或他們自己的任何屬性。只有評論可以。我的朋友是如此堅持以至於有效率。最後,我說:「好的,如果你想要我創建一個單獨的表並讓'person'成爲它自己的字段,那麼第二個字段是什麼?因爲如果一個表只有一列,那麼看起來毫無意義。我們以後可能會創造一個需要給予'人'它自己的桌子,但我們可以處理那個。「然後他說,字符串不能是主鍵,並且我們會將當前表中的'persons'轉換爲數字,並且這些數字將成爲新'person'表中的主鍵。對我而言,這看起來沒有必要,它會使當前的表更難以閱讀。他還認爲,以後不可能創建第二張表格,而且我們現在需要預測我們以後可能需要它。

誰是對的?

回答

9

在我看來,你的朋友是對的。

人應該生活在不同的表中,你應該嘗試正常化。不過,不要過度。

從長遠來看,您可能希望在網站上做更多的事情,比如說要將多個文件附加到某個人(即,圖片),你會非常感謝,然後爲正常化。

+0

我同意弗蘭基/你的朋友。以後做這種改變雖然不是不可能,但是很尷尬,容易出錯。 – Jaydee 2010-09-10 15:41:26

+2

任何人都可以解釋如何爲任何功能依賴性的左側沒有出現的屬性創建代理鍵來標準化數據庫嗎?正如OP所說,Person決定什麼都不會(並且永遠不會)。你會爲名爲'Stuff'的屬性提供相同的建議嗎?這裏可能有一個正常化問題,但它不涉及Person。 – NealB 2010-09-10 20:47:37

+0

@NealB我作爲一名教師的經歷以及提問的方式讓我相信OP是有偏見的。簡單的事實是,該字段稱爲人而不是文本,與IMO相關。 – Frankie 2010-09-10 22:03:24

3

我會投你的朋友。我喜歡規範化和規劃未來,即使你從不需要它,這種規範化過程也非常容易,而且不需要花費時間。您可以創建一個查詢視圖,以使您的SQL更清晰,並且無需您自己加入表。

0

這是交易。每當你創造一些東西時,你都要確保它有成長的空間。您想嘗試預測未來的項目以及您計劃的未來進展。在這種情況下,你說得沒錯,現在不需要添加一個持有1個字段的人表(不包括ID,假設你有一個int ID字段和一個人名)。但是,將來您可能希望爲這些人提供其他屬性,例如名字,姓氏,電子郵件地址,添加的日期等。

儘管過度規範化肯定是有害的,但我個人會創建另一個,更大的桌子可以容納帶有其他字段的人員,以便我可以在未來輕鬆添加新功能。

+1

是不是真的很難在稍後時刻將所有'獨特'條目從'person'中拉出來,並將它們作爲新表中的一列?並使用字符串作爲主鍵有問題嗎? – 2010-09-10 16:05:13

+1

使用字符串作爲你的PK只會讓事情變得更加困難。大量的DBMS允許你使用自動遞增的數字ID,所以你並不需要關心發生錯誤的可能性。具有數字ID而不是字符串更有意義。 – Aaron 2010-09-10 20:36:52

1

那麼,有兩種思想流派。有人說,儘可能以最標準化的方式創建數據模型,然後在需要更高效率時取消規範化。另一個基本是「做這項工作所需的最低工作,然後根據你的要求改變」。也被稱爲YAGNI(你不需要它)。

這一切都取決於你看到了這一切。如果這是全部,那麼你的方法可能很好。如果你打算隨着時間推移改進它的新功能,那麼你的朋友是對的。

2

你說得對。

Person可能是一般的事情,但不是在你的模型。如果你打算讓人們正確地識別他們正在談論的人,那麼需要一個Person表。例如,如果評論僅針對已經在數據庫中註冊的人員。

但在這裏它看起來像你有一個非結構化數據,而無需識別;並沒有什麼/沒有人有興趣確定「jenny」和「jennyyy」是否實際上是同一個人,更不用說「jenny doe」和「我的表弟」...

7

創建一個新表人和使用該表的關鍵字代替人的屬性與標準化無關。由於其他原因,這可能是一個好主意,但這樣做並不會使數據庫「更規範化」而不是不這樣做。所以你是對的:就標準化而言,創建另一個表是不必要的。

1

標準化是所有關於函數依賴(FD的)。在完全標準化之前,您需要確定數據模型屬性中存在的 FD的全部

讓審覈你有什麼:

  • 一個CommentId的任何給定的情況下功能決定了Person(FD:CommentId - >Person
  • 一個CommentId的任何給定的情況下功能決定了Comment(FD: CommentId - >Comment
  • 任何給定的CommentId實例在功能上決定了UserId(FD: CommentId - >UserId
  • 一個CommentId的任何給定的實例功能確定Score(FD:CommentId - 這裏>Score

一切都是單獨CommentIdCommentId從屬屬性。這可能導致您認爲包含上述屬性的全部或部分屬性的關係(表格)必須進行標準化。

首先要問自己的是,爲什麼您創建了CommentId屬性呢?嚴格來說, 這是一個製造的屬性 - 它不涉及任何'真實'。 CommentId是 通常被稱爲代理鍵。代理鍵只是一個組成的值,其值爲 ,表示與其他一組屬性相對應的唯一值集合。那麼CommentId 是什麼樣的屬性呢?我們可以明白這 出通過提出下列問題,並增加新的FD對模型:

  • 1)評論是否必須是唯一的?如果是這樣,FD:Comment - >CommentId必須爲真。
  • 2)只要是關於不同的人,可以多次進行相同的評論?如果是,則 FD:Person + Comment - >CommentId必須爲真,並且上面1中的FD是錯誤的。
  • 3)可以同一個評論多次提出關於同一個人提供的 不同UserId的?如果是,則1和2中的FD不能爲真,但是 FD:Person + Comment + UserIdCommentId可能是對的。
  • 4)可以通過同一個UserId對同一個人進行多次相同的評論,但 有不同的評分?這意味着FD:Person + Comment + UserId'+ Score - >CommentId是真的,其他人是假的。

上面的4個FD中的一個必須是真的。無論它是否影響數據模型的標準化。

假設FD:Person + Comment + UserId - >CommentId證明是正確的。邏輯 後果是:

  • Person + Comment + UserIdCommentId服務方面等同鍵Score
  • Score應放在關係與之一,但不是它的鍵都(以避免傳遞依賴)。 明顯的選擇是CommentId,因爲它是專門創建的替代品。
  • 甲關係組成:CommentIdPersonCommentUserId被扎 關鍵其替代需要。

從理論的角度來看,是不是 所需的代理鍵CommentId,讓您的數據模型和數據庫工作。然而,它的存在可能會影響關係的構建。

創建代理鍵是一個很重要的實際問題。 考慮,如果你選擇不使用代理鍵,但全 屬性在其位置設置Person + Comment + UserId可能發生的事情,尤其是當它需要在多個表的外鍵或主鍵 :

  • 註釋可能會將多個空間開銷 添加到您的數據庫,因爲它在多個表中重複。它可能不止是幾個字符長。
  • 如果有人選擇編輯評論,會發生什麼?該更改需要傳播 到註釋是密鑰一部分的所有表。不是一個美麗的景象!
  • 索引長期複雜的按鍵會佔用大量的空間和/或作出更新緩慢性能

分配給代理鍵不會改變,無論你做什麼,相關的屬性值 值它確定。現在更新從屬屬性 限於定義代理鍵的一個表。這具有巨大的現實意義。

現在回到您是否應該創建Person的替代品。 Person在許多或任何FD的左側是否存在 ?如果確實如此,它的價值將通過你的數據庫傳播,並且有一種情況可以爲它創建一個替代品。 Person是文本還是數字屬性與創建代理鍵的選擇無關。

根據你所說的,最好的辦法是創建一個 替代品Person。這種說法是基於懷疑它的價值可能在某個時候成爲未來某個關鍵點或關鍵點的一部分。

1

如果您從不打算將person列與用戶或其他任何事物相關聯,並且數據顯然不需要一致性或數據完整性檢查,那麼爲什麼這是關係數據庫呢?這不是一個nosql數據庫的用例嗎?或者我錯過了什麼?

0

無論您何時與用戶打交道,都應該有專門的表格。然後,您可以加入表格並引用該用戶的ID。

user -> id | username | password | email 

comment -> id | user_id | content 

SQL加入評論的用戶:

SELECT user.username, comment.content FROM user JOIN comment WHERE user.id = comment.user_id; 

這將使其在未來變得更輕鬆,當你想找到有關該特定用戶的信息。額外的努力量可以忽略不計。

關於每個評論的「評分」,這也應該是一個單獨的表格。這樣你可以將用戶連接到「喜歡」或「不喜歡」。

0

有了這個數據庫,你可能會覺得它沒問題,但是當你希望用戶從數據庫中知道更多信息時,將來可能會有一些問題。假設你想知道關於一個人的評論數量名字='abc'。在這種情況下,你將不得不瀏覽整個評論表並且繼續計數。在這個位置,你可以爲每個人設置一個名爲'count'的屬性,並且每當評論時就增加它是在那個人身上製造的。
就規範化而言,擁有規範化數據庫總是會更好,因爲它可以減少冗餘並使數據庫直觀易懂。如果您預計未來您的數據庫將會變大,那麼標準化必須存在。