1. 程式人生 > >mysql 索引實踐(二) 聯合索引

mysql 索引實踐(二) 聯合索引

#emp_no PRIMARY
#first_name,last_name,gender  idx_first_name_last_name

show index from employees

 最左匹配:

    不是指的順序,而是where 中將根據聯合索引的建立順序,去檢索當前SQL能用到該聯合索引到哪一步。

    first_name,last_name,gender :可匹配 (first_name)、(first_name,last_name)、(first_name,last_name,gender)

#ref
explain select * from employees where first_name = 'Parto1'
#ref
#Using where
explain select * from employees where first_name = 'Parto1' and birth_date = '1953-09-02'
#ref
#Using where
explain select * from employees where first_name = 'Parto1' and birth_date != '1953-09-02'


#ALL
#Using where
explain select * from employees where first_name != 'Parto1'

     若聯合索引的第一個欄位為不等值查詢,則該SQL一定不走該聯合索引。

此時,可以發現是否使用和SQL中欄位的順序無關

此時,當前SQL能用到該聯合索引 first_name,last_name

#ref
explain select * from employees where first_name = 'Parto1' and last_name =  'Parto1'
#ref
explain select * from employees where last_name = 'Parto1' and first_name =  'Parto1'
#ref
#Using where
explain select * from employees where birth_date = '1953-09-02'  and first_name =  'Parto1' and last_name =  'Parto1'
explain select * from employees where first_name =  'Parto1' and birth_date = '1953-09-02' and last_name =  'Parto1'
explain select * from employees where first_name =  'Parto1' and last_name =  'Parto1' and birth_date = '1953-09-02'
explain select * from employees where first_name =  'Parto1' and last_name =  'Parto1' and birth_date != '1953-09-02'
explain select * from employees where first_name =  'Parto1' and last_name =  'Parto1' and birth_date is not null

 

此時,當前SQL能用到該聯合索引 first_name

#range
#Using index condition
explain select * from employees where first_name =  'Parto1' and last_name !=  'Parto1'
explain select * from employees where first_name =  'Parto1' and last_name !=  'Parto1' and gender = 'M'
explain select * from employees where first_name =  'Parto1' and last_name !=  'Parto1' and gender != 'M'
explain select * from employees where first_name =  'Parto1' and last_name is not null and gender is not null
explain select * from employees where first_name =  'Parto1' and last_name !=  'Parto1' and birth_date = '1953-09-02'
explain select * from employees where first_name =  'Parto1' and last_name !=  'Parto1' and birth_date != '1953-09-02'

此時,當前SQL不能用到該聯合索引

#ALL
#Using where
explain select * from employees where first_name !=  'Parto1' and last_name =  'Parto1'
explain select * from employees where first_name !=  'Parto1' and last_name =  'Parto1' and gender = 'M'
explain select * from employees where first_name !=  'Parto1' and last_name =  'Parto1' and birth_date = '1953-09-02'

    總之, 對於聯合索引,會將SQL中的欄位按照索引的順序去匹配,若某一欄位未匹配上,或者該欄位查詢為不等值查詢,該索引將只執行到該欄位之前,在此之後的欄位,即使匹配且為等值查詢,也將不再繼續進行匹配了。

    因此,如果若第一個欄位就匹配不上或者該欄位為不等值查詢,則一定為全表掃描。

    例如,(A,B,C) 如果B 缺失或者B為不等值查詢,則索引將只執行到A,此時B,C不執行。

不滿足所有列均為索引

#ALL
#Using where
explain select * from employees where first_name = 'Parto1' or last_name =  'Parto1'
explain select * from employees where first_name = 'Parto1' or birth_date = '1953-09-02'

 

滿足所有列均為索引

#index_merge
#Using union(idx_first_name_last_name,PRIMARY); Using where
explain select * from employees where first_name = 'Parto1' and last_name =  'Parto1' and gender = 'M' or emp_no = 10005

 

不滿足所有列均為索引

#ALL
#Using where
explain select * from employees where first_name = 'Parto1' and last_name =  'Parto1' and gender = 'M' or birth_date = '1953-09-02'

#使用OR連線時:
#1.1 當所有的列均為索引,且為等值查詢,仍將採用index_merge 進行查詢
#1.2 若有一列不是索引,此時將全表掃描;
#1.3 若至少有一列的索引不是等值查詢,此時將全表掃描