背景
關於innodb內的索引大小。對於表
create table `testtb` (
`id` int(11) not null auto_increment,
`a` int(11) default null,
`b` int(11) default null,
`c` int(11) default null,
primary key (`id`),
key `i1` (`a`),
key `i2` (`a`,`id`),
key `i3` (`id`,`a`)
) engine=innodb default charset=utf8;
由於innodb在儲存索引的時候會自動取出重複的主鍵,原始碼分析見這裡
先說幾個結論
1)index i2 由於索引定義中已經包含pk id,因此不會存兩份,實際就是(a, id)
2)index i1 本身要包含主鍵id,因此也是(a, id),與i2 相同
3)同理1,index i3 裡存的也只是(id, a)
異常
按照上面的結論,以下操作能發現「異常」
create table `t1` (
`id` int(11) not null auto_increment,
`a` int(11) default null,
`b` int(11) default null,
`c` int(11) default null,
primary key (`id`),
key `i2` (`a`,`id`)
) engine=innodb default charset=utf8;
create table `testtb` (
`id` int(11) not null auto_increment,
`a` int(11) default null,
`b` int(11) default null,
`c` int(11) default null,
primary key (`id`),
key `i3` (`id`,`a`)
) engine=innodb default charset=utf8;
接下來往這個兩個表中各插入5w行記錄,插入語句類似
foreach i in 1 to 5w
插入資料完成後,這個兩個表索引大小是否相同?
從show table status like 『%t1%』; 和show table status like 『%t2%』;的index_length可以看出來,是不同的,t1大一些。
儲存的行數相同,資料也相同,為什麼大小不一樣?
原因說明
主要在於插入順序導致的**。在上面的例子中,由於a,b,c的值都是隨機值,導致索引(a, id)是隨機的。id是遞增的,所以(id, a)是遞增的。
隨機插入索引和順序遞增插入索引之所以有差別,就在於隨機插入會導致更多的btree**。
這也就是為什麼在某些場景下,我們建議在表比較大的應用中,用自增id替代unique key (並非唯一的原因,也不是固定的規範,需要具體分析)。
驗證
有了上面的分析,要驗證就比較簡單了,把兩個表清空(truncate),
插入資料改為如下的語句
foreach i in 1 to 5w
這樣插入的每行都是(n,n,n,n), n為1到5w的遞增。這樣索引(a, id)也是順序遞增方式,與(id,a)一樣緊湊,再看show table status能發現一樣了。
有個工具
分兩個表驗證比較麻煩。這個是之前寫過的乙個分析檔案利用率的工具ibd_used
,可以看乙個表上各個索引的大小和索引上page的利用率。
用法./ibd_used testtb.ibd 0 n > k
說明:第乙個引數是要分析的ibd檔案 第
二、三個引數是起始、結束page_no。如果你要分析整個檔案,n可以輸入乙個很大的數就行。
結果中會輸出每個page的利用率,因此比較多,記得重定向輸出
最後幾行是整個索引的統計結果。
用文章開頭的例子和隨機值插入的case,得到的表中,執行
ibd_used data/test/testtb.ibd 0 99999999 > k
最後幾行如下
index_id:1517 rate 1751652/1949696=0.898423
index_id:1518 rate 701314/1212416=0.578443
index_id:1519 rate 701314/1212416=0.578443
index_id:1520 rate 700828/770048=0.910109
按順序對應索引,可以看出,i1和i2的利用率一模一樣,但跟i3 比起來就差多了。
grep -po " index_id:\d+" k | sort | uniq -c
120 index_id:1517
75 index_id:1518
75 index_id:1519
48 index_id:1520
這個命令看每個索引占用多少page,與我們的結論一致:i3因為緊湊,所以占用更少的page。
innodb的索引機制
1 innodb將資料和索引儲存在一起 2 innodb索引是基於b tree的clustered index,b tree中的每個結點儲存key row data innodb中的第二個索引儲存,在搜尋時,先通過key找到pk,再通過pk搜尋b tree的結點,從中找到row data 3 由於聚...
InnoDB的索引模型
在 mysql 中,索引是在儲存引擎層實現的,儲存引擎沒有統一的索引標準,所以在不同儲存引擎中索引的工作方式並不一樣。即使多個儲存引擎支援同一種型別的索引,其底層的實現也可能不同。而在mysql 資料庫中,innodb 儲存引擎的使用最為廣泛,所以我們來了解一下innodb 的索引模型。innodb...
InnoDB索引實現
1 innodb的資料檔案本身就是索引檔案。從上文知道,myisam索引檔案 是分離的,索引檔案僅儲存資料記錄的位址。而在innodb中,表資料 檔案本身就是按b tree組織的乙個索引結構,這棵樹的葉節點data域 儲存了完整的資料記錄,這個索引的key是資料表的主鍵,因此innodb 表資料檔案...