MySQL中InnoDB儲存B 樹的應用

2021-10-05 17:53:31 字數 4250 閱讀 4536

聯合索引和單列的索引的建立方法是一樣的, 不同的只是對多個列進行索引.聯合索引的本質上也是一棵b+樹, 而b+樹都是按照鍵值(key)排序的, 單列索引的鍵值只有乙個, 而聯合索引的鍵值是有多個.

建立一張表如下:

create

table t1 (

id int(11

)auto_increment

notnull

, a int(11

)not

null

, b int(11

)not

null

,primary

key(id)

,key idx_a_b(a,b));

# 插入資料

insert

into t1 select1,

1,1;

insert

into t1 select2,

1,2;

insert

into t1 select3,

2,1;

insert

into t1 select4,

2,2;

insert

into t1 select5,

3,1;

此時, 索引idx_a_b儲存的鍵值順序是(1,1), (1,2),(2,1),(2,2),(3,1). 對於查詢select * from t1 where a=*** and b=***則可以使用這個索引, 對於查詢單列a的查詢select * from t1 where a=***也可以使用這個聯合索引, 然而對於查詢select * from t1 where b=***是不可以使用這個索引的, 因為在索引表的b+樹上, 不是按照b列的值來排序的.

聯合索引的第二個好處是, 對於第二列也進行了排序, 考慮如下場景:

在購物**, 需要查詢某個使用者最近3次的購物記錄
建表如下所示:

create

table buy_log (

user_id int(11

)not

null

, buy_date date

notnull,)

;# 插入資料

insert

into buy_log values(1

,'2019-03-22');

insert

into buy_log values(2

,'2019-01-14');

insert

into buy_log values(2

,'2019-05-01');

insert

into buy_log values(1

,'2019-06-16');

insert

into buy_log values(1

,'2019-09-24');

insert

into buy_log values(3

,'2019-10-02');

insert

into buy_log values(1

,'2019-12-30');

# 分貝建立兩個索引測試

alter

table buy_log add

key(user_id)

;alter

table buy_log add

key(user_id, buy_date)

;

執行explain select * from buy_log where user_id = 3;操作, 發現使用的是uer_id這個索引, 因為user_id=3這個行在儲存中只是乙個單行資料.

執行explain select * from buy_log where user_id = 2;操作, 發現使用的是user_id_2這個聯合索引, 因為在user=2是乙個多值結果,

執行explain select * from buy_log where user_id = 2 order by buy_date desc limit 3;

操作, 發現使用的是user_id_2索引, 因為聯合索引上已經對buy_date進行了排序.

因為聯合索引(a, b) 是按照a,b排序的, 所以如下操作也可以直接或得結果:

select

*from

table t1 where a=*** order

by b;

對於聯合索引(a,bc)來說, 下列語句同樣可以獲取到直接的結果:

select

*from

table t1 where a=*** and b=*** order

by c;

但是如下語句, 無法直接通過聯合索引獲取, 還需要進行一次filesort操作:

select

*from

table t1 where a=*** order

by c;

兩個作用:

對於通過主鍵或者索引的鍵可以直接從索引的b+中獲取, 無需查詢聚集索引, 減少io.

對於某些統計問題, 也可以直接通過覆蓋索引完成, 而無需訪問聚集索引.

innodb儲存引擎支援覆蓋索引.所謂覆蓋索引(covering index), 即是直接從輔助索引中獲取到需要查詢的記錄. 使用覆蓋索引的好處是, 相對於聚集索引, 不需要查詢包含整個行的資料, 而只是需要查詢某個列的資料, 所以覆蓋索引的io操作遠遠小於聚集索引.

innodb儲存引擎的輔助索引的葉子節點是包含主鍵的, 其儲存形式如下:

(primary key1, primary key2, ..., key1, key2, ...)
primary keyn: 代表主鍵中的第n個鍵.

keyn: 代表輔助索引中的第n個鍵.

得出結論: 我們可以通過以keyn或者primary keyn為查詢條件, 相互查詢到其他的key的值. 例如:

select

primary key2, key3 from t1 where key1=***;

select key2, key3 from t1 where

primary key1=***;

對於select count(1) from t1這樣的語句, 可以直接通過覆蓋索引完成.

當我們使用explain檢查查詢語句的時候, 發現優化器進行了權標掃瞄, 而沒有使用索引, 這種情況多發生在範圍查詢或者join連線操作時候.

建立表如下:

create

table order_details(

order_id int(11

)not

null

, prod_id int(11

)not

null

,index idx_order_id(order_id)

,index idx_order_id_prod_id(order_id, prod_id));

# 插入資料

insert

into order_details(order_id, prod_id)

values(1

,2);

insert

into order_details(order_id, prod_id)

values(2

,3);

insert

into order_details(order_id, prod_id)

values(1

,2);

insert

into order_details(order_id, prod_id)

values(1

,5);

insert

into order_details(order_id, prod_id)

values(2

,7);

MySQL儲存引擎 InnoDB

為什麼innodb不將總數存起來?innodb直接count 會遍歷全表 沒有where條件 雖然結果準確,但會導致效能問題。按照效率排序的話,count 字段 innodb一棵b 樹可以存放多少行資料?這個問題的簡單回答是 約2千萬。為什麼是這麼多呢?因為這是可以算出來的,要搞清楚這個問題,我們先...

MySql中innodb儲存引擎事務日誌詳解

mysql會最大程度的使用快取機制來提高資料庫的訪問效率,但是萬一資料庫發生斷電,因為快取的資料沒有寫入磁碟,導致快取在記憶體中的資料丟失而導致資料不一致怎麼辦?innodb主要是通過事務日誌實現acid特性,事務日誌包括 重做日誌redo和回滾日誌undo。redo記錄的是已經全部完成的事務,就是...

MySQL的儲存引擎INNODB

1 一般情況下,mysql會預設提供多種儲存引擎,你可以通過下面的檢視 看你的mysql現在已提供什麼儲存引擎 mysql show engines 看你的mysql當前預設的儲存引擎 mysql show variables like storage engine 你要看某個錶用了什麼引擎 在顯示...