簡體   English   中英

數據庫表可以沒有主鍵嗎?

[英]Can a database table be without a primary key?

誰能告訴我關系數據庫中的表(例如MySQL / SQL SERVER)是否可以沒有主鍵?

例如,我可以有一個表day_temperature ,在其中注冊temperaturetime 我不知道為這樣的表設置主鍵的原因。

從技術上講,您可以聲明這樣的表。

但是,在您的情況下,應該將time設置為PRIMARY KEY ,因為同時具有不同的溫度可能是錯誤的,並且多次具有相同的溫度可能沒有用。

從邏輯上講,每個表都應具有一個PRIMARY KEY以便您可以區分兩個記錄。

如果您的數據中沒有候選鍵,則只需創建一個替代鍵( AUTO_INCREMENTSERIAL或數據庫提供的任何替代鍵)。

沒有PRIMARY KEY的唯一借口是日志或類似的表,該表受制於DML並且具有索引會影響性能,超出容忍度。

像往常一樣取決於它

不必具有主鍵。 更重要的是擁有正確的索引 在數據庫引擎上,取決於主鍵如何影響索引 (即為主鍵列/列創建唯一索引)。

但是,就您而言(還有99%的其他情況),我將添加一個新的自動增量唯一列,temp_id並使其替代主鍵。

維護該表變得容易得多 -例如查找和刪除記錄(即重復的記錄)-相信我-每個表都有時間來解決問題:(。

主鍵自然不是時間嗎? 在給定的時間內,您是否會遇到多個溫度?

一個更好的問題是:“為什么使用主鍵就可以創建表?”

如果可能存在重復條目(例如同一時間)的問題,並且您不必查詢特定記錄或記錄范圍,則可以不用任何鍵。

您不需要PK,但建議您擁有一個。 這是識別唯一行的最佳方法。 有時,您不希望使用自動增量int PK,而是在其他對象上創建PK。 例如,在您的情況下,如果每次僅存在一個唯一行,則應在該時間上創建PK。 它使基於時間的查找更快,並且可以確保它們是唯一的(可以確保不違反數據完整性):

我將包含一個替代/自動增量鍵,尤其是在有可能重復時間/溫度讀數的情況下。 您將沒有其他方法來唯一標識重復的行。

我在做過的一張桌子上遇到了同樣的問題。

問題在於,應該由表的所有行組成PK,這一切都很好,但這意味着表的大小將隨着插入的每一行而快速增長。

我選擇不具有PK,而僅在執行查詢的行上具有索引。

時間將成為您的主鍵。 它將幫助為該列建立索引,以便您可以根據日期范圍查詢數據。 PK最終使您的行變得唯一,因此在您的示例中,datetime是PK。

當您在mysql上復制數據庫時,沒有主鍵的表可能會導致復制延遲。

http://lists.mysql.com/mysql/227217

使用ROW或MIXED時,最常見的錯誤是無法驗證要復制的每個表上是否都有PRIMARY KEY。 這是一個錯誤,因為當將ROW事件(例如上面記錄的事件)發送到從屬服務器,並且該表的主服務器副本和從屬服務器副本都在表上沒有PRIMARY KEY時,無法輕松識別出哪個您希望復制更改的唯一行。

根據您的回答,我將考慮三種選擇:

  • 在兩個列上都放置一個PK,這樣每次每次只能有一個溫度,反之亦然。 此解決方案允許具有相同溫度或相同時間的多行,只是不會有任何兩行具有相同的溫度AND時間。
  • 完全不輸入PK,而是在兩個列上都放置唯一索引。 一個包含兩個列的唯一索引。 這將允許溫度和時間為空,但會產生更多空間來維護索引。

如果您有大量的讀取,這兩個選項對於檢索速度是最好的,但是由於索引也必須更新,因此插入率會降低。

  • 根本不放置任何索引,也不輸入PK。 這對於插入是最好的,但對於搜索卻很不利。 對於通過其他機制進行檢索或不需要插入設備檢查重復的日志記錄很有用。

同樣,在此處考慮基數並考慮使用自動遞增數字的未來后果也非常重要。 如果您打算進行很多插入操作,那么即使自動遞增無符號bigint也將是一個風險,因為它最終會用完。 在您的示例中,我想您每天將保存數據-多長時間? 如果您每分鍾都保存溫度,那將是一個問題。因此,我將舉一個極端的例子。

我想最好是從桌子上考慮一下您的需求。 您是否全年都在每分鍾進行一次“保存后忘記”操作? 您要在業務邏輯中的實時決策中頻繁使用此表嗎? 我認為最好將實時(oltp)所需的數據與很少需要的長期保存數據區分開,並且允許其較高的檢索延遲(olap)。 甚至值得將數據復制到兩個不同的表中,其中一個被嚴格索引並偶爾被擦除以控制基數,第二個實際上被保存在幾乎沒有索引的中間磁盤上(可以從您的數據庫中傳輸模式主fs轉換為另一個fs)。

即使您沒有在MySQL中向InnoDB表添加主鍵,MySQL也會向該表添加隱藏的聚集索引。 如果您未定義主鍵,則MySQL會在所有鍵列都不為NULL的情況下找到第一個UNIQUE索引,InnoDB會將其用作聚集索引。

如果表沒有主鍵或合適的UNIQUE索引,則InnoDB在包含行ID值的綜合列上內部生成聚集索引GEN_CLUST_INDEX。

https://dev.mysql.com/doc/refman/8.0/zh-CN/innodb-index-types.html

我有一個不需要主鍵的表的更好示例-聯接表。 假設我有一個表包含一個稱為“功能”的表,另一個表包含一個名為“組”的表,並且我想要一個聯接器表,該表告訴我所有組可能具有的所有功能,所以基本上

create table capability_group
(  capability_id varchar(32),
    group_id     varchar(32));

沒有理由對此有主鍵,因為您永遠不會尋址一行-您要么想要給定組的所有功能,要么想要給定功能的所有組。 最好在(capabilty_id,group_id)上有唯一的約束,並在兩個字段上使用單獨的索引。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM