目錄
1.何種查詢支持索引?
2.注意事項和建議
一 何種查詢支持索引?
1 MySQL 目前支持前導列
就目前來說,mysql 暫時只支持最左前綴原則進行篩選。
例子:創建復合索引
create index idx_a_b_c on tb1(a,b,c)
只有使用如下條件才可能應用到這個復合索引
1.where a=?
2.where a = ? and b = ?
3.where a = ? and b = ? and c = ?
但
4.where a = ? and c = ?
只會使用到mysql 索引 a 列的信息
2.索引列上的范圍查找
對于某個條件進行范圍查找時,如果這個列上有索引,且使用 where ... between
and ... > ,< 等范圍操作,那么可能用到索引范圍查找,如果索引范圍查找的成本太高,數據庫可能會選擇全表掃描的方式
。
注意 in 不屬于范圍查找的范疇
3.join 列
在聯合查詢兩個表時,比如查詢語句為 select a.col1,b.col2 from a join b on a.id = b.id,
其中id 為兩個表的主鍵,如果a是小表,那么a 就被視為驅動表,那么數據庫可能全表掃描a 表,
并用 a表的每個id 去探測b表的索引查詢匹配的記錄。
4.where 子句
形如:
where a = ? and b = ? and c>1000
where a = ? and b = ? and c = ? and d>1000
where 子句的條件列是復合索引前面的索引列+另一個列的范圍查找
create index idx_a_b_c_d on tb1(a,b,c,d);
形如:
where a = ? and b = ? and c>1000
where a = ? and b = ? and c = ? and d>1000
才會用到這個索引
下面兩個查詢:
where a = ? and b =? and c>10000 and d< 10000
這個例子中d
d <10000這個操作不會走索引
where a >? and b =? and c>10000 and d< 10000
這個例子中a列上有范圍查找,那么b、c、d列上的索引信息都不能被利用
原則,創建索引,考慮把復合索引的范圍查找放到最后。
5.mysql 優化器
mysql 優化器會做一些特殊優化,比如對于索引查找max(索引列)可以直接進行定位。遇到max,min 是可以在列上做索引。
二 注意事項和建議
1.where 條件中的索引列不能是表達式的一部分,mysql 不支持函數索引
2.InnoDB 二級索引底層葉子極點存儲的是索引+主鍵值
InnoDB 的非主鍵索引存儲的不是實際的記錄的指針,而是主鍵的值,所以主鍵最好是整數型,如自增ID ,基于主鍵存取數據是最高效的,使用二級索引存取數據則需要進行二次索引查找。
3.索引盡量是高選擇性的
而且要留意基數值,基數值指的是一個列中不同值的個數,顯然,
最大基數意味著該列中的每個值都是唯一的,最小基數意味著該列中的所有值都是相同的,索引列的基數相對于表的行數較高時,
也就重復值更少,索引的工作效果更好。
有種情況雖然基數很小,但由于數據分布很不均勻因此也會導致某些記錄數很小,
那么這種情況也適合建立索引加速查找這部分數據。
4.使用更短的索引
可以考慮前綴索引,但應確保選擇的前綴的長度可以保證大部分值是唯一的。
如:alter table test add key(col(6))
衡量不同前綴索引唯一值比例。
select count(distinct left(col_name,5))/count(*) As sele5,
select count(distinct left(col_name,6))/count(*) As sele6,
select count(distinct left(col_name,7))/count(*) As sele7,
select count(distinct left(col_name,8))/count(*) As sele8,
select count(distinct left(col_name,9))/count(*) As sele9
from table_name;
5.避免創建過多的索引
索引過多可能會浪費大量空間
尤其本身字段量較大的字符串,索引過多可能會浪費空間,且降低修改數據的速度,
所以,不要創建過多的索引,也不要創建重復的索引。
6.如果是唯一值得列,創建唯一索引會更佳,也可以確保不會出現重復數據.
7.使用覆蓋索引能大大提高性能
覆蓋索引:所有數據都可以從索引中得到,而不需要去讀物理記錄。例如某個復合索引idx_a_b_c 建立在表tb1 的 a、b、c 列上,
那么對于如下的sql 語句
select a,b from tb1 where a = ? and b = ? and c =?
mysql可以直接從索引idx_a_b_c 中獲取數據。使用覆蓋索引也可以避免二次索引查找。
使用explain 命令輸出查詢計劃,如果extra列是“using index ” 那就表示使用的是覆蓋索引。
8.利用索引來排序
mysql 有兩種方式可以產生有序結果,一種是使用文件排序,另一種是掃描有序的索引,我們盡量使用索引來排序
注意事項:
1. 盡量保證索引列和order by 的列相同,且各列按照相同的順序排序。
比如在表table1 的復合索引idx_a_b_c(創建在a,b,c上);
如:select * from table1 order by a,b,c;
select * from table1 where a=? and b =? order by c
以上查詢都可以利用有序索引來加速檢索順序。
2.如果連接多張表,那么order by 引用的列需要再表連接順序的首張表內。
9 添加冗余索引需要權衡:
如果一個索引column A 那么一個新的索引(columnA,columnB)就是冗余索引
一般情況下不論是新增冗余索引,還是擴展原索引為冗余索引,都會導致索引文件的增大,并且增加了維護索引的開銷。
比如更改了列值,并且在此列上建立了索引,那么這個列值更改之后,索引是要進行重新排序的。