MySQL 爲何須要一個主鍵

主鍵mysql

表中每一行都應該有能夠惟一標識本身的一列(或一組列)。sql

一個顧客可使用顧客編號列,而訂單可使用訂單ID,僱員可使用僱員ID 或 僱員社會保險號。數據庫

主鍵(primary key) 一列(或一組列),其值可以惟一區分表中的每一個行。 惟一標識表中每行的這個列(或這組列)稱爲主鍵。沒有主鍵,更新或刪除表中特定行很困難,由於沒有安全的方法保證只設計相關的行。緩存

雖然並不老是都須要主鍵,但大多數數據庫設計人員都應保證他們建立的每一個表有一個主鍵,以便於之後數據操縱和管理安全

表中的任何列均可以做爲主鍵,只要它知足一下條件:數據庫設計

一、任何兩行都不具備相同的主鍵值 二、每一個行都必須具備一個主鍵值(主鍵列不容許NULL值)oop

主鍵值規範:這裏列出的規則是MySQL自己強制實施的。優化

主鍵的最好習慣: 除MySQL強制實施的規則外,應該堅持的幾個廣泛認爲的最好習慣爲:設計

一、不更新主鍵列的值 二、不重用主鍵列的值 三、不在主鍵列中使用可能會更改的值(例如,若是使用一個名字做爲主鍵以標識某個供應商,應該供應商合併和更改其名字時,必須更改這個主鍵)索引

總之:不該該使用一個具備意義的column(id 自己並不保存表 有意義信息) 做爲主鍵,而且一個表必需要有一個主鍵,爲方便擴展、鬆耦合,高可用的系統作鋪墊。

很是感謝 @pathbox、 @est、@hooooopo 同窗的提醒。主鍵的做用,在於索引。

無特殊需求下Innodb建議使用與業務無關的自增ID做爲主鍵

InnoDB引擎使用匯集索引,數據記錄自己被存於主索引(一顆B+Tree)的葉子節點上。這就要求同一個葉子節點內(大小爲一個內存頁或磁盤頁)的各條數據記錄按主鍵順序存放,所以每當有一條新的記錄插入時,MySQL會根據其主鍵將其插入適當的節點和位置,若是頁面達到裝載因子(InnoDB默認爲15/16),則開闢一個新的頁(節點)

一、若是表使用自增主鍵,那麼每次插入新的記錄,記錄就會順序添加到當前索引節點的後續位置,當一頁寫滿,就會自動開闢一個新的頁。以下圖所示:

這樣就會造成一個緊湊的索引結構,近似順序填滿。因爲每次插入時也不須要移動已有數據,所以效率很高,也不會增長不少開銷在維護索引上。

二、 若是使用非自增主鍵(若是身份證號或學號等),因爲每次插入主鍵的值近似於隨機,所以每次新紀錄都要被插到現有索引頁得中間某個位置:

此時MySQL不得不爲了將新記錄插到合適位置而移動數據,甚至目標頁面可能已經被回寫到磁盤上而從緩存中清掉,此時又要從磁盤上讀回來,這增長了不少開銷,同時頻繁的移動、分頁操做形成了大量的碎片,獲得了不夠緊湊的索引結構,後續不得不經過OPTIMIZE TABLE來重建表並優化填充頁面。

在使用InnoDB存儲引擎時,若是沒有特別的須要,請永遠使用一個與業務無關的自增字段做爲主鍵。

InnoDB 存儲引擎採用了彙集(clustered)的方式,所以每張表的存儲都是按主鍵的順序進行存放。若是沒有顯式地在表定義時指定主鍵,InnoDB存儲引擎會爲每一行生成一個6字節的ROWID,並一次做爲主鍵。

mysql 在頻繁的更新、刪除操做,會產生碎片。而含碎片比較大的表,查詢效率會下降。此時需對錶進行優化,這樣纔會使查詢變得更有效率。

很是感謝 @xiaoronglv 同窗

If you define a PRIMARY KEY on your table, InnoDB uses it as the clustered index. If you do not define a PRIMARY KEY for your table, MySQL picks the first UNIQUE index that has only NOT NULL columns as the primary key and InnoDB uses it as the clustered index. 具體參考 14.2.10.1 Clustered and Secondary Indexes

相關文章
相關標籤/搜索