MySQL如何使用索引

初始化測試數據


創建一個測試用的表

create table dept(
id int primary key auto_increment ,
deptName varchar(32) not null unique,
salary decimal(12,6) not null,
remark varchar(256),
createDate date);


在表中插入一萬條數據

BEGIN

Declare i int default 0;
while(i<=10000) do
begin
select i;
set i=i+1;
insert into dept(deptName,salary,createDate,remark) values(i,20000,now(),‘test’);
end ;
End while;
END


通過EXPLAIN分析SQL的執行計劃

在這裏插入圖片描述
type:表示MySQL在表中找到所需行的方式,或者叫訪問類型,常見類型如下(從左到右,性能由差到好)

ALL index range ref eq_ref const,system NULL

ALL: 全表掃描

index: 索引全掃描

range:索引範圍掃描

ref:使用非唯一索引掃描

eq_ref:使用唯一索引掃描

const,system:單表中最多隻有一個匹配行

以上:通過explain分析type是ALL 是性能最差的一種 以下:開始優化。


MySQL中BTREE索引的用法

普通的BTREE索引

優化前 explain select remark from dept where deptName = ?; type ALL

增加索引 ALTER TABLE dept ADD INDEX index_remark (remark);

優化測試 explain select remark from dept where deptName = ?; type ref

聯合BTREE索引

增加聯合索引 ALTER TABLE dept ADD INDEX index_all (deptName,remark,createDate);

explain select deptName,remark,createDate from dept where deptName=‘2’ and remark = 'test’and createDate =‘2018-07-22’;—— type ref

但是explain select deptName,remark,createDate from dept where remark = 'test’and createDate =‘2018-07-22’; ——type index

——type從ref(使用非唯一索引掃描)變成了index(索引全掃描),

上面兩個SQL 索引相同 Type不同是因爲 BTREE索引中匹配最左前綴 比如給col1+col2+col3字段上加聯合索引能夠被包含col1+col2 、col1+col2+col3、col1+col3使用(順序沒有影響 比如 where col1=? and col2=? 和 where col2=? and col1=? 結果一樣)

使用聯合索引 相當於一下子創建瞭如上的三個索引,這就是聯合索引的好處


存在索引但不能使用索引的經典場景

例句:explain select deptName,remark,createDate from dept where deptName=‘2’ and remark = 'test’and createDate =‘2018-07-22’;
——type ref

下面是反面教材:

1.以%開頭的LIKE查詢不能使用BTREE索引

explain select deptName,remark,createDate from dept where deptName like’%2’ and remark = 'test’and createDate =‘2018-07-22’; type index

2.數據類型出現隱式轉換時也不能使用索引

explain select deptName,remark,createDate from dept where deptName =2 and remark = 'test’and createDate =‘2018-07-22’; type index

3.複合索引時 不符合最左匹配原則(上面已經提到)

explain select deptName,remark,createDate from dept where remark = 'test’and createDate =‘2018-07-22’; type index

4.用or分隔開的條件,如果or前的條件中的列有索引,後面的列中沒有索引,那麼涉及到的索引都不會使用到

explain select deptName,remark,createDate from dept where deptName =‘2’ and remark = 'test’and createDate =‘2018-07-22’ or salary =200; type ALL


Order By語句

order by 字段混合使用DESC ASC 不會使用索引

select * from table order by key1 desc,key2 asc (儘量不要出現這種混合排序)

Where條件過濾的關鍵字和Order by中所使用的不同 不會使用索引

select * from table where key2 = ? order by key1 (order by 出現的關鍵字 儘量 在where條件中也出現)
    


優化Group By語句

當我們的SQL語句需要Group By分組時:

explain分析SQL的時候 Extra那一列有時候會出現 using Filesort表示需要額外的排序 如果業務沒有要求排序 我們可以通過禁止排序, 加上 Order By NULL 有時候可以去掉using filesort
  


MySQL應不應該加唯一約束和外鍵約束

外鍵約束可以通過代碼控制,加起來開發很不方便不建議加。如果業務需要唯一約束,因爲唯一約束代碼很難控制,必須加

對於唯一約束,有人說先查出來數據庫已經存在的 再去判斷傳值存不存在。這樣的缺點 1.查詢所有已經存在的很費時間,2.需要考慮併發 不然重複數據還是會進入到數據庫

一旦進入了錯誤數據 以後想加唯一約束都加不上了

查詢語句關鍵字使用順序: WHERE GROUP BY HAVING ORDER BY DESC LIMIT


補充

唯一索引

explain select deptName,remark,createDate from dept where id=2; type const 像這種利用唯一索引做where條件的效率最高 (主鍵默認被加上了唯一索引)

SQL表連接查詢時 表連接的條件(也就是外鍵)必須加索引(阿里巴巴代碼規範看到的)

重要: 多表連接的時候 join on(a.id=b.id2) 連接外鍵id、id2 必須加索引。MySQL規定作爲外鍵的字段必須有索引 也是爲了讓我們表連接的時候 用到索引(其實做到這點 基本上足夠優化百分之八十的SQL了)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章