詳解MySQL資料庫設計之innodb如何設計主鍵索引

2019-10-22     波波說運維

概述

今天主要看下innodb是怎麼去設計主鍵索引的,這裡引用了一個淘寶MySQL資料庫經典案例。


innodb 主鍵索引

在Innodb中,聚簇索引默認就是主鍵索引。如果沒有主鍵,則按照下列規則來建聚簇索引:

沒有主鍵時,會用一個非空並且唯一的索引列做為主鍵,成為此表的聚簇索引;

如果沒有這樣的索引,InnoDB會隱式定義一個主鍵來作為聚簇索引。

由於主鍵使用了聚簇索引,如果主鍵是自增id,那麼對應的數據也會相鄰地存放在磁碟上,寫入性能較高。如果是uuid等字符串形式,頻繁的插入會使innodb頻繁地移動

磁碟塊,寫入性能就比較低了。

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. If there is no such index in the table, InnoDB internally generates a clustered index where the rows are ordered by the row

ID that InnoDB assigns to the rows in such a table. The row ID is a 6-byte field that increases monotonically as new rows are inserted. Thus, the rows

ordered by the row ID are physically in insertion order.

InnoDB是clustered-index table,因此對於InnoDB而言,主鍵具有特殊意義。可以通過主鍵直接定位到對應的某一數據行記錄的物理位置,主鍵索引指向對應行記錄,其他索引則都指向主鍵索引;因此,可以這麼說,InnoDB其實就是一個 B+樹索引,這棵B+樹的索引就是主鍵,它的值則是對應的行記錄。

在InnoDB數據表設計中,我們需要注意幾點:

  • 1. 顯式的定義一個 INT 類型自增欄位的主鍵,這個欄位可以僅用於做主鍵,不做其他用途
  • 2. 如果不顯式定義主鍵的話,可能會導致InnoDB每次都需要對新數據行進行排序,嚴重損害性能
  • 3. 儘量保證不對主鍵欄位進行更新修改,防止主鍵欄位發生變化,引發數據存儲碎片,降低IO性能
  • 4. 如果需要對主鍵欄位進行更新,請將該欄位轉變成一個唯一索引約束欄位,另外創建一個沒有其他業務意義的自增欄位做主鍵
  • 5. 主鍵欄位類型儘可能小,能用SMALLINT就不用INT,能用INT就不用BIGINT
  • 6. 主鍵欄位放在數據表的第一順序

再看一個淘寶MySQL經典案例

1、創建表

大多數網際網路業務(用戶,消息)都可以用A表或者B表滿足需求,那麼兩個表有什麼區別呢?

--創建表A
CREATE TABLE `A` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`message_id` int(11) NOT NULL,
`user_id` int(11) NOT NULL,
`msg` varchar(1024) DEFAULT NULL,
`gmt_create` datetime NOT NULL,
PRIMARY KEY (`id`),
KEY `user_id` (`user_id`,`message_id`),
KEY `idx_gmt_create` (`gmt_create`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
--創建表B
CREATE TABLE `B` (
`user_id` int(11) NOT NULL,
`message_id` int(11) NOT NULL,
`msg` varchar(1024) DEFAULT NULL,
`gmt_create` datetime NOT NULL,
PRIMARY KEY (`user_id`,`message_id`),
KEY `idx_gmt_create` (`gmt_create`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

2、對比分析

AB表對比分析如下:


總結

因為主鍵是clustered index,採用自增id可以減少insert的時間。自增最大的問題就是分表分庫。 數據整合。 如果增加序列分發器 帶來的消耗也很高。 數據存儲碎片也難以消除。 主鍵設計是個折中的取捨。

覺得有用的朋友多幫忙轉發哦!後面會分享更多devops和DBA方面的內容,感興趣的朋友可以關注下~


文章來源: https://twgreatdaily.com/zh/lNHc8G0BMH2_cNUgiMoO.html