mysql索引
使用索引是提高數據庫查詢效率的主要方式,下面從索引結構,索引類型,索引操作,命中索引幾個方面來介紹索引。
一、索引結構
mysql5.5以上的默認存儲引擎innodb,只顯式支持BTree( 事實上從數據結構上來講是B+樹,mysql稱之為BTree)索引,對於頻繁訪問的表,innodb會建立自適應hash索引,
即在B樹索引基礎上建立hash索引,可以顯著提高查找效率,用戶是無法自己指定的,除此之外還有Hash索引和全文索引(fullText索引)。
BTree索引
BTree,顧名思義,就是所有的索引節點都按照balance tree的數據結構來存儲。BTree結構可以顯著減少定位記錄時所經歷的中間過程,從而加快存取速度。
Btree中,每個結點包含:
1、本結點所含關鍵字的個數;
2、指向父結點的指針;
3、關鍵字;
4、指向子結點的指針;
更詳細的B+樹介紹參考https://www.cnblogs.com/yangecnu/p/Introduce-B-Tree-and-B-Plus-Tree.html
Hash索引
Hash 索引由於使用了hash表結構,其檢索效率很高,索引的檢索可以一次定位,不像B+樹索引需要從根節點到枝節點,
所以 Hash 索引的查詢效率要遠高於 B+樹 索引。但是,Hash索引的使用范圍非常有限。
1.在MySQL中,只有HEAP/MEMORY引擎表才能支持哈希索引,InnoDB引擎的自適應哈希索引(adaptive hash index)不
能在創建索引時指定。
2.Hash索引僅支持=,>=,<=這幾種條件運算,不支持排序,范圍內查找,like等查詢。
3.Hash索引不支持組合索引中部分索引的查找。
4.當Hash值重復較多時,索引速度可能不如BTree索引。
FullText索引
Full-text索引就是我們常說的全文索引,他的存儲結構也是Btree。主要是為了解決在我們需要用like查詢的低效問題。
只能解決’xxx%’的like查詢。如:字段數據為ABCDE,索引建立為A、AB、ABC、ABCD、ABCDE五個。
二、索引類型
索引一般有:普通索引,唯一索引,復合索引這幾種類型。
唯一索引:唯一索引要求字段中不會出現重復數據。
復合索引:將多個字段組合起來作為索引,必須使用到該索引中的第一個字段作為條件時才能保證系統使用該索引,否則該索引將不會被使用。
三、索引操作
建立索引:
create index 索引名 on 表名(索引字段名)
建立唯一索引:
create unique index 索引名 on 表名(索引字段名)
建立復合索引:
create index 索引名 on 表名(索引字段名1,索引字段名2...)
查看表中索引:
show index from 表名
刪除索引:
drop index 索引名 on 表名
查看索引是否命中
Mysql:當結果的type為 index時索引命中
explain +sql語句
Oracle:
explain plan for+sql語句
四、命中索引
1. 避免判斷null值
應盡量避免在 where 子句中對字段進行 null 值判斷,否則將導致引擎放棄使用索引而進行全表掃描,如:
select id from t where num is null
可以在num上設置默認值0,確保表中num列沒有null值,然后這樣查詢:
select id from t where num=0
2. 避免不等值判斷
應盡量避免在 where 子句中使用!=或<>操作符,否則引擎將放棄使用索引而進行全表掃描。
3. 避免使用or邏輯
應盡量避免在 where 子句中使用 or 來連接條件,否則將導致引擎放棄使用索引而進行全表掃描,
select id from t where num=1 or num=2
可以使用union all來進行查詢來命中索引如:
select id from t where num=1 union all select id from t where num=2
4 . 慎用in和not in邏輯
in 和 not in 也要慎用,否則會導致全表掃描,如:
select id from t1 where num in(select id from t2 where id > 10)
此時外層查詢會全表掃描,不使用索引。可以修改為:
select id from t1,(select id from t1 where id > 10)t2 where t1.id = t2.id
此時索引被使用,可以明顯提升查詢效率。
5. 注意模糊查詢
下面的查詢也將導致全表掃描:
select id from t where name like '%abc%'
不要在like條件左邊加'%',這樣不會走索引模糊查詢如果是必要條件時,可以使用
select id from t where name like 'abc%'
來實現模糊查詢,此時索引將被使用。如果頭匹配是必要的,可以使用elasticsearch等全文搜索引擎。
6. 避免查詢條件中字段計算
應盡量避免在 where 子句中對字段進行表達式操作,這將導致引擎放棄使用索引而進行全表掃描。如:
select id from t where num/2=100
應改為:
select id from t where num=100*2
7. 避免查詢條件中對字段進行函數操作
應盡量避免在where子句中對字段進行函數操作,這將導致引擎放棄使用索引而進行全表掃描。如:
select id from t where substring(name,1,3)='abc'
name以abc開頭的id
應改為:
select id from t where name like 'abc%'
8. “=”左邊避免表達式運算
不要在 where 子句中的“=”左邊進行函數、算術運算或其他表達式運算,否則系統將可能無法正確使用索引。
9. 組合索引使用
在使用索引字段作為條件時,如果該索引是復合索引,那么必須使用到該索引中的第一個字段作為條件時才能保證系統使用該索引,否則該索引將不會被使用,並且應盡可能的讓字段順序與索引順序相一致。
10 exists
很多時候用 exists 代替 in 是一個好的選擇:
select num from a where num in(select num from b)
用下面的語句替換:
select num from a where exists(select 1 from b where num=a.num)