目錄
1.何種查詢支持索引碴里?
2.注意事項和建議
一 何種查詢支持索引漱受?
1 MySQL 目前支持前導列
就目前來說化借,mysql 暫時只支持最左前綴原則進行篩選。
例子:創(chuàng)建復合索引
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 ... > ,< 等范圍操作休雌,那么可能用到索引范圍查找灶壶,如果索引范圍查找的成本太高,數(shù)據(jù)庫可能會選擇全表掃描的方式
杈曲。
注意 in 不屬于范圍查找的范疇
3.join 列
在聯(lián)合查詢兩個表時驰凛,比如查詢語句為 select a.col1,b.col2 from a join b on a.id = b.id,
其中id 為兩個表的主鍵,如果a是小表担扑,那么a 就被視為驅動表恰响,那么數(shù)據(jù)庫可能全表掃描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列上的索引信息都不能被利用
原則枢劝,創(chuàng)建索引,考慮把復合索引的范圍查找放到最后卜壕。
5.mysql 優(yōu)化器
mysql 優(yōu)化器會做一些特殊優(yōu)化您旁,比如對于索引查找max(索引列)可以直接進行定位。遇到max轴捎,min 是可以在列上做索引鹤盒。
二 注意事項和建議
1.where 條件中的索引列不能是表達式的一部分,mysql 不支持函數(shù)索引
2.InnoDB 二級索引底層葉子極點存儲的是索引+主鍵值
InnoDB 的非主鍵索引存儲的不是實際的記錄的指針侦副,而是主鍵的值侦锯,所以主鍵最好是整數(shù)型,如自增ID ,基于主鍵存取數(shù)據(jù)是最高效的跃洛,使用二級索引存取數(shù)據(jù)則需要進行二次索引查找率触。
3.索引盡量是高選擇性的
而且要留意基數(shù)值终议,基數(shù)值指的是一個列中不同值的個數(shù)汇竭,顯然,
最大基數(shù)意味著該列中的每個值都是唯一的穴张,最小基數(shù)意味著該列中的所有值都是相同的细燎,索引列的基數(shù)相對于表的行數(shù)較高時,
也就重復值更少皂甘,索引的工作效果更好玻驻。
有種情況雖然基數(shù)很小,但由于數(shù)據(jù)分布很不均勻因此也會導致某些記錄數(shù)很小,
那么這種情況也適合建立索引加速查找這部分數(shù)據(jù)璧瞬。
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.避免創(chuàng)建過多的索引
索引過多可能會浪費大量空間
尤其本身字段量較大的字符串,索引過多可能會浪費空間访诱,且降低修改數(shù)據(jù)的速度垫挨,
所以,不要創(chuàng)建過多的索引触菜,也不要創(chuàng)建重復的索引九榔。
6.如果是唯一值得列,創(chuàng)建唯一索引會更佳涡相,也可以確保不會出現(xiàn)重復數(shù)據(jù).
7.使用覆蓋索引能大大提高性能
覆蓋索引:所有數(shù)據(jù)都可以從索引中得到帚屉,而不需要去讀物理記錄。例如某個復合索引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 中獲取數(shù)據(jù)生逸。使用覆蓋索引也可以避免二次索引查找牢屋。
使用explain 命令輸出查詢計劃,如果extra列是“using index ” 那就表示使用的是覆蓋索引槽袄。
8.利用索引來排序
mysql 有兩種方式可以產(chǎn)生有序結果烙无,一種是使用文件排序,另一種是掃描有序的索引遍尺,我們盡量使用索引來排序
注意事項:
1. 盡量保證索引列和order by 的列相同截酷,且各列按照相同的順序排序。
比如在表table1 的復合索引idx_a_b_c(創(chuàng)建在a,b,c上)乾戏;
如:select * from table1 order by a,b,c;
select * from table1 where a=? and b =? order by c
以上查詢都可以利用有序索引來加速檢索順序迂苛。
2.如果連接多張表,那么order by 引用的列需要再表連接順序的首張表內(nèi)鼓择。
9 添加冗余索引需要權衡:
如果一個索引column A 那么一個新的索引(columnA,columnB)就是冗余索引
一般情況下不論是新增冗余索引三幻,還是擴展原索引為冗余索引,都會導致索引文件的增大呐能,并且增加了維護索引的開銷念搬。
比如更改了列值,并且在此列上建立了索引,那么這個列值更改之后朗徊,索引是要進行重新排序的首妖。