Foreign-Key

建構盡可能多的外鍵是一種好習慣嗎?

  • December 16, 2017

例如,有三個表:playersdungeonsinstances

一個player有很多dungeons,一個dungeon有很多instances,就像一個著名的魔獸世界遊戲。每個player都有一個dungeon_id作為外鍵,每個dungeon都有一個instance_id作為外鍵。那將是一種足夠的極簡主義方法。player每一個都instance可以通過dungeon表訪問。這將減少 1 列,但查詢時間更長。

另一種方法是作為外鍵添加player_id到表中。instances現在玩家可以直接從instances表中查詢。更短的查詢,但外鍵多一列。

從長遠來看,哪種方法更好?在實踐中,似乎在邏輯上可能的任何地方都添加外鍵會更容易。但是這不會導致更緊密的耦合併使程式碼更難重構嗎?

理想情況下,實體不應該有外鍵,應該被認為是主人。所以playerdungeon並且instance是擁有與他們自己的特徵相關的資訊/屬性/欄位的大師。您可以為Enitity-Relations提供一個單獨的表。因此,您將擁有player_dungeonand dungeon_instance(根據 PS,兩者都是一對多)。在這裡,如果你想知道instances屬於一個player,你需要加入這兩個表。

現在出現了著名的辯論:規範化與非規範化。第一種方法是書本上的,並且會奏效。但是隨著表的增長很難擴展(儘管有適當的索引)。因此,您嘗試根據這些表上發生的查詢量對上述解決方案進行非規範化。

player每一個都instance可以通過dungeon表訪問。

由於您在此處指定了一個查詢,我假設這是一個頻繁查詢(瓶頸)。如果有很多這樣的查詢,你可以有另一個關係表player_instance。現在我們已經解決了延遲的問題,但產生了一個更大的問題:

一致性:現在有兩種方法可以找到instances屬於 a 的player。一種是直接按player_instance表,另一種是通過player_dungeon和連接dungeon_instance。我們必須始終從這兩種方法中得到相同的答案。為了確保我們現在需要讓我們的寫入受到影響。如何?

  • 在添加每個玩家-地牢映射時,除了進入我們的 player_dungeon表之外,我們還需要插入到player_instance 表中(我們必須查詢dungeon_instance以查看映射到該特定地牢的所有實例)。
  • 在添加新dungeon_instance玩家時,我們需要將所有現有玩家映射到我們映射到特定地牢的實例。聽起來不太好,是嗎?

我們還沒有完成。所有這些操作都應該是原子的(即在事務中),否則會在短時間內出現不一致。

最後,我們需要做出取捨。您想讓您的數據庫讀取速度變慢還是寫入受到影響?您是否需要使您的系統響應/可用或一致?決定權在你。

詳情請閱讀CAP 定理

引用自:https://dba.stackexchange.com/questions/193292