MySQL 數(shù)據(jù)庫索引使用場景&注意事項(xiàng)

目錄

1.何種查詢支持索引?
2.注意事項(xiàng)和建議

一 何種查詢支持索引?

1 MySQL 目前支持前導(dǎo)列


就目前來說,mysql 暫時(shí)只支持最左前綴原則進(jìn)行篩選。
例子:創(chuàng)建復(fù)合索引
create index idx_a_b_c on tb1(a,b,c)
只有使用如下條件才可能應(yīng)用到這個(gè)復(fù)合索引
1.where a=?
2.where a = ? and b = ?
3.where a = ? and b = ? and c = ?
但
4.where a = ? and c = ?
只會(huì)使用到mysql 索引 a 列的信息

2.索引列上的范圍查找


對于某個(gè)條件進(jìn)行范圍查找時(shí),如果這個(gè)列上有索引,且使用 where ... between 
and ... > ,< 等范圍操作,那么可能用到索引范圍查找,如果索引范圍查找的成本太高,數(shù)據(jù)庫可能會(huì)選擇全表掃描的方式
。
注意 in  不屬于范圍查找的范疇

3.join 列


在聯(lián)合查詢兩個(gè)表時(shí),比如查詢語句為 select a.col1,b.col2 from a join b on a.id = b.id,
其中id 為兩個(gè)表的主鍵,如果a是小表,那么a 就被視為驅(qū)動(dòng)表,那么數(shù)據(jù)庫可能全表掃描a 表,
并用 a表的每個(gè)id 去探測b表的索引查詢匹配的記錄。

4.where 子句


形如:
where a = ? and b = ? and c>1000
where a = ? and b = ? and c = ? and d>1000

where 子句的條件列是復(fù)合索引前面的索引列+另一個(gè)列的范圍查找

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
才會(huì)用到這個(gè)索引

下面兩個(gè)查詢:
where a = ? and b =? and c>10000 and d< 10000
這個(gè)例子中d 
d <10000這個(gè)操作不會(huì)走索引
where a >? and b =? and c>10000 and d< 10000
這個(gè)例子中a列上有范圍查找,那么b、c、d列上的索引信息都不能被利用
原則,創(chuàng)建索引,考慮把復(fù)合索引的范圍查找放到最后。

5.mysql 優(yōu)化器


mysql 優(yōu)化器會(huì)做一些特殊優(yōu)化,比如對于索引查找max(索引列)可以直接進(jìn)行定位。遇到max,min  是可以在列上做索引。

二 注意事項(xiàng)和建議


1.where 條件中的索引列不能是表達(dá)式的一部分,mysql 不支持函數(shù)索引

2.InnoDB 二級索引底層葉子極點(diǎn)存儲(chǔ)的是索引+主鍵值

InnoDB 的非主鍵索引存儲(chǔ)的不是實(shí)際的記錄的指針,而是主鍵的值,所以主鍵最好是整數(shù)型,如自增ID ,基于主鍵存取數(shù)據(jù)是最高效的,使用二級索引存取數(shù)據(jù)則需要進(jìn)行二次索引查找。

3.索引盡量是高選擇性的

而且要留意基數(shù)值,基數(shù)值指的是一個(gè)列中不同值的個(gè)數(shù),顯然,
最大基數(shù)意味著該列中的每個(gè)值都是唯一的,最小基數(shù)意味著該列中的所有值都是相同的,索引列的基數(shù)相對于表的行數(shù)較高時(shí),
也就重復(fù)值更少,索引的工作效果更好。
有種情況雖然基數(shù)很小,但由于數(shù)據(jù)分布很不均勻因此也會(huì)導(dǎo)致某些記錄數(shù)很小,
那么這種情況也適合建立索引加速查找這部分?jǐn)?shù)據(jù)。

4.使用更短的索引

可以考慮前綴索引,但應(yīng)確保選擇的前綴的長度可以保證大部分值是唯一的。
如: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)建過多的索引

索引過多可能會(huì)浪費(fèi)大量空間
尤其本身字段量較大的字符串,索引過多可能會(huì)浪費(fèi)空間,且降低修改數(shù)據(jù)的速度,
所以,不要?jiǎng)?chuàng)建過多的索引,也不要?jiǎng)?chuàng)建重復(fù)的索引。

6.如果是唯一值得列,創(chuàng)建唯一索引會(huì)更佳,也可以確保不會(huì)出現(xiàn)重復(fù)數(shù)據(jù).

7.使用覆蓋索引能大大提高性能

覆蓋索引:所有數(shù)據(jù)都可以從索引中得到,而不需要去讀物理記錄。例如某個(gè)復(fù)合索引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 命令輸出查詢計(jì)劃,如果extra列是“using index ” 那就表示使用的是覆蓋索引。

8.利用索引來排序

mysql 有兩種方式可以產(chǎn)生有序結(jié)果,一種是使用文件排序,另一種是掃描有序的索引,我們盡量使用索引來排序
 注意事項(xiàng):
   1. 盡量保證索引列和order by 的列相同,且各列按照相同的順序排序。
    比如在表table1 的復(fù)合索引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 添加冗余索引需要權(quán)衡:

  如果一個(gè)索引column A 那么一個(gè)新的索引(columnA,columnB)就是冗余索引
  一般情況下不論是新增冗余索引,還是擴(kuò)展原索引為冗余索引,都會(huì)導(dǎo)致索引文件的增大,并且增加了維護(hù)索引的開銷。
  比如更改了列值,并且在此列上建立了索引,那么這個(gè)列值更改之后,索引是要進(jìn)行重新排序的。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容