[英]Can a database table be without a primary key?
誰能告訴我關系數據庫中的表(例如MySQL / SQL SERVER)是否可以沒有主鍵?
例如,我可以有一個表day_temperature
,在其中注冊temperature
和time
。 我不知道為這樣的表設置主鍵的原因。
從技術上講,您可以聲明這樣的表。
但是,在您的情況下,應該將time
設置為PRIMARY KEY
,因為同時具有不同的溫度可能是錯誤的,並且多次具有相同的溫度可能沒有用。
從邏輯上講,每個表都應具有一個PRIMARY KEY
以便您可以區分兩個記錄。
如果您的數據中沒有候選鍵,則只需創建一個替代鍵( AUTO_INCREMENT
, SERIAL
或數據庫提供的任何替代鍵)。
沒有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時,無法輕松識別出哪個您希望復制更改的唯一行。
根據您的回答,我將考慮三種選擇:
如果您有大量的讀取,這兩個選項對於檢索速度是最好的,但是由於索引也必須更新,因此插入率會降低。
同樣,在此處考慮基數並考慮使用自動遞增數字的未來后果也非常重要。 如果您打算進行很多插入操作,那么即使自動遞增無符號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.