mysql建表語句主鍵自增 MYSQL索引 上

2021-10-11 16:05:28 字數 2020 閱讀 6040

前言

今天同事做資料清理的時候發現我這邊有一張表沒有主鍵,這個表有兩個字段,id和name,id作者唯一索引,在我印象裡,乙個資料表如果沒有主鍵索引,它會內部建立主鍵索引,建立的標準就是唯一性,我覺得應該是使用id建立內部的主鍵索引。 所以,會有兩個問題

第乙個問題,如果確實使用id建立了內部的主鍵索引,直接通過id查詢確實只會有一次 b+ 樹的搜尋,這樣的話唯一索引其實就是沒有意義的浪費。

第二個問題,如果不是通過id建立內部的主鍵索引,而且通過其他方式內建的主鍵索引,那麼 id查詢就需要就需要先通過二級索引 id 搜尋 b+ 樹 查詢到主鍵索引,再通過主鍵索引搜尋b+樹查詢到資料記錄,得需要兩次的 索引樹的查詢。

所以這種做法怎麼著都是不合理的。 下午補習了丁奇老師的 mysql45講 的關於索引的的兩節 深入淺出索引,做個筆記

我們都知道,innodb 使用了 b+ 樹索引模型,資料都是儲存在 b+ 樹的葉子節點上的。每乙個索引都會對應乙個 b+ 樹。 簡單的建表語句,id是主鍵索引,k是普通索引,對應兩顆b+ 樹

索引k是1對應的id是100,以此類推,2對應200,3對應300... 可以看到 主鍵索引的葉子節點存的是整行資料,也稱聚簇索引 非主鍵索引的葉子節點內容是主鍵的值,也稱二級索引

根據上面的索引結構說明,我們來討論乙個問題:基於主鍵索引和普通索引的查詢有什麼區別?

b+ 樹為了維護索引有序性,在插入新值的時候需要做必要的維護。以上面這個圖為例,如果插入新的行 id 值為 700,則只需要在 r5 的記錄後面插入乙個新記錄。如果新插入的 id 值為 400,就相對麻煩了,需要邏輯上挪動後面的資料,空出位置。 而更糟的情況是,如果 r5 所在的資料頁已經滿了,根據 b+ 樹的演算法,這時候需要申請乙個新的資料頁,然後挪動部分資料過去。這個過程稱為頁**。在這種情況下,效能自然會受影響。 除了效能外,頁**操作還影響資料頁的利用率。原本放在乙個頁的資料,現在分到兩個頁中,整體空間利用率降低大約 50%。當然有**就有合併。當相鄰兩個頁由於刪除了資料,利用率很低之後,會將資料頁做合併。合併的過程,可以認為是**過程的逆過程。

基於上面的索引維護過程說明,我們來討論乙個案例:

你可能在一些建表規範裡面見到過類似的描述,要求建表語句裡一定要有自增主鍵。當然事無絕對,我們來分析一下哪些場景下應該使用自增主鍵,而哪些場景下不應該。
自增主鍵是指自增列上定義的主鍵,在建表語句中一般是這麼定義的: not null primary key auto_increment。 插入新記錄的時候可以不指定 id 的值,系統會獲取當前 id 最大值加 1 作為下一條記錄的 id 值。 也就是說,自增主鍵的插入資料模式,正符合了我們前面提到的遞增插入的場景。每次插入一條新記錄,都是追加操作,都不涉及到挪動其他記錄,也不會觸發葉子節點的**。 而有業務邏輯的字段做主鍵,則往往不容易保證有序插入,這樣寫資料成本相對較高。

除了考慮效能外,我們還可以從儲存空間的角度來看。假設你的表中確實有乙個唯一字段,比如字串型別的身份證號,那應該用身份證號做主鍵,還是用自增欄位做主鍵呢? 由於每個非主鍵索引的葉子節點上都是主鍵的值。如果用身份證號做主鍵,那麼每個二級索引的葉子節點占用約 20 個位元組,而如果用整型做主鍵,則只要 4 個位元組,如果是長整型(bigint)則是 8 個位元組。

顯然,主鍵長度越小,普通索引的葉子節點就越小,普通索引占用的空間也就越小。
所以,從效能和儲存空間方面考量,自增主鍵往往是更合理的選擇。有沒有什麼場景適合用業務字段直接做主鍵的呢?還是有的。 比如,有些業務的場景需求是這樣的: 只有乙個索引;該索引必須是唯一索引。 你一定看出來了,這就是典型的 kv 場景。由於沒有其他索引,所以也就不用考慮其他索引的葉子節點大小的問題。 這時候我們就要優先考慮上一段提到的「盡量使用主鍵查詢」原則,直接將這個索引設定為主鍵,可以避免每次查詢需要搜尋兩棵樹。

mysql 主鍵自增語句 MySQL 自增主鍵

以下僅考慮 innodb 儲存引擎。自增主鍵有兩個性質需要考慮 單調性每次插入一條資料,其 id 都是比上一條插入的資料的 id 大,就算上一條資料被刪除。連續性插入成功時,其資料的 id 和前一次插入成功時資料的 id 相鄰。自增主鍵的單調性 為何會有單調性的問題?這主要跟自增主鍵最大值的獲取方式...

建表主鍵自增 Oracle建表,建主鍵,自增

oracle建表,建主鍵,自增 建表 create table test id number 4 not null primary key,name varchar2 25 序列 create sequence test sequence increment by 1 每次增加幾個 start wi...

mysql建表語句

在sql語句中注意 約束的概念 1.實體完整性約束 主鍵 唯一且非空 primary key 違約處理 no action 拒絕執行 2.參照完整性約束 外來鍵約束 foregin key references tablename filedname on delete update casecad...