如果大家正在尋找一個java的學習環境,或者在開發中遇到困難,可以加入我們的java學習圈,點擊即可加入,共同學習,節約學習時間,減少很多在學習中遇到的難題。
常用主鍵生成方式
- Mysql自增長主鍵策略
這種簡單,不需要程序特別處理 ,但是這種方法對項目移植到其它數據庫上改動會比較大,oracle、db2采用Sequence,Mysql、sqlServer又采用自增長,通用性不好 。 - 使用時間戳相關生成策略
這種實現簡單,與數據庫無關,移植性較好 ,但長度太長,最少也得20位;
比如雪花算法,可以生成20位有序的的ID。 - UUID、GUID
這種方式簡單,代碼方便,全球唯一,與數據庫無關,移植性較好,但沒有排序,無法保證趨勢遞增。UUID往往是使用字符串存儲,查詢的效率比較低。 - 每次取主鍵最大值+1做為新的主鍵
這種主鍵長度可控,移植性較好 ,但并發寫可能會造成主鍵沖突,對并發也不太好控制 - 單獨建一個存放主鍵的表
這種實現簡單,移植性較好 ,需要考慮并發問題,整個系統主鍵生成都依賴該表,性能影響可能較大
默認主鍵
如果我們定義了主鍵(PRIMARY KEY),那么InnoDB會選擇主鍵作為聚集索引;
如果沒有顯式定義主鍵,則InnoDB會選擇第一個不包含有NULL值的唯一索引作為主鍵索引;
如果也沒有這樣的唯一索引,則InnoDB會選擇內置6字節長的ROWID作為隱含的聚集索引(ROWID隨著行記錄的寫入而主鍵遞增,這個ROWID不像ORACLE的ROWID那樣可引用,是隱含的)。
自增的好處
數據記錄本身被存于主索引(一顆B+Tree)的葉子節點上。這就要求同一個葉子節點內(大小為一個內存頁或磁盤頁)的各條數據記錄按主鍵順序存放,因此每當有一條新的記錄插入時,MySQL會根據其主鍵將其插入適當的節點和位置,如果頁面達到裝載因子(InnoDB默認為15/16),則開辟一個新的頁(節點);
如果表使用自增主鍵,那么每次插入新的記錄,記錄就會順序添加到當前索引節點的后續位置,當一頁寫滿,就會自動開辟一個新的頁;
如果使用非自增主鍵(如果身份證號或學號等),由于每次插入主鍵的值近似于隨機,因此每次新紀錄都要被插到現有索引頁得中間某個位置,此時MySQL不得不為了將新記錄插到合適位置而移動數據,甚至目標頁面可能已經被回寫到磁盤上而從緩存中清掉,此時又要從磁盤上讀回來,這增加了很多開銷,同時頻繁的移動、分頁操作造成了大量的碎片,得到了不夠緊湊的索引結構,后續不得不通過OPTIMIZE TABLE來重建表并優化填充頁面。
擴展
主鍵盡量采用自增方式,InnoDB 表實際是一棵索引組織表,順序存儲可以提高存取效率,充分利用磁盤空間。
還有對一些復雜查詢可能需要自連接來優化時需要用到。
如果沒有主鍵或唯一索引,update/delete 是通過所有字段來定位操作的行,相當于每行就是一次全表掃描。