聯合索引和單列的索引的建立方法是一樣的, 不同的只是對多個列進行索引.聯合索引的本質上也是一棵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 你要看某個錶用了什麼引擎 在顯示...