create
table staffs(
id int
primary
keyauto_increment
, name varchar(24
)not
null
default
''comment
'姓名'
, age int
notnull
default
0comment
'年齡'
, pos varchar(20
)not
null de****t''
comment
'職位'
, add_time timestamp
notnull ****ult current_timestamp
comment
'入職時間'
)charset utf8 comment
'員工記錄表'
;insert
into staffs(name,age,pos,add_time)
values
('z3'
,'22'
,'manager'
,now()
);insert
into staffs(name,age,pos,add_time)
values
('july'
,'23'
,'dev'
,now()
);insert
into staffs(name,age,pos,add_time)
values
('2000'
,'23'
,'dev'
,now()
);alter
table staffs add
index idx_staffs_nameagepos(name,age,pos)
;
仔細看我的sql語句,建立乙個員工表staffs,插入了三行資料,建立了索引idx_staffs_nameagepos(name,age,pos)
索引的三個值按順序都用上是效果最好的,如圖
如果索引了多列,要遵循該法則。該法則指的是查詢從索引的最左前列開始並且不跳過索引中的列。
如上面的索引idx_staffs_nameagepos(name,age,pos)
中:
假設跳過了name直接查詢,那麼是全表掃瞄,這裡不做圖示,這種情況下你的索引完全沒用到。
假設有name開頭,跳過了age,用了pos,即跳過了中間的索引列,那麼索引其實只會用到name而已,如圖:
說明:有沒有用到pos欄位查詢,圖中的ref列都只有乙個const,如果pos有用上,那麼二表的ref列應該有兩個const,說明pos沒用上索引,同時key_len列也能說明這個問題。
如圖,left(name,4)='july』是mysql的函式,表示查詢name欄位左邊起4位的值為』july』的結果。
從結果上來說,和上面的select語句查詢結果是一致的,但是因為在索引列上做了操作,導致了索引失效。
前後兩句sql語句中,age欄位因為變成了範圍查詢,所以age欄位不再在索引裡起到檢索的作用,而是起到排序的作用,並且pos欄位完全失效。
何以見得?
因為首先,如果只用到name欄位,那麼key_len的值應該為74而非78,下圖是三個字段逐步使用時key_len的值:
那麼現在key_len的值為78而非74,就說明age欄位有在用,索引的作用不只有查詢,還有排序,age的查詢作用變弱,並且直接影響到後面的pos索引查詢失效,那麼age起作用的就是排序。
只訪問索引的查詢,即索引列和查詢列一致,減少使用select *。
即,在這個表中最好使用select name,age,pos
。這個要根據實際業務來。
注意:這裡的<> 就是不等於,它是乙個符號,而不是小於和大於兩個符號。
但是右邊可以加%(如』abc%』),這樣索引不會失效。
這裡會有乙個面試題:解決like '%字串%'時索引不被使用的方法?
答案:使用覆蓋索引。select 主鍵/索引的任意乙個字段都行/最好是按索引順序來(只是最好)
,在本案例中,索引欄位為name,age,pos。
可行的情況:
select id where 哪個字段都行 like
'%aa%'
;//主鍵
select age where 哪個字段都行 like
'%aa%'
;//索引單獨第二位第三位也行
select age,pos where 哪個字段都行 like
'%aa%'
;//索引第二位第三位一起也行
select name where 哪個字段都行 like
'%aa%'
;//索引第一位肯定行
不行的情況:
//皆為有不是索引的字段
select
*where 哪個字段都行 like
'%aa%'
;select age,add_time where 哪個字段都行 like
'%aa%'
;
這個問題的起因是這樣的:
mysql的功能比較強大,在本案例的表中,name欄位有乙個值是2000,那麼在mysql中,select * from staffs where name='2000'
和select * from staffs where name=2000
都能查出來資料且結果一樣。
但是mysql底層執行時,name欄位本身是varchar型別,後一句select中2000是int型別,mysql自己會做乙個轉化,用的就是函式,那麼參考第3條,索引就失效了。
雖然查詢結果一樣,但查詢效率變低了。
假設有索引index(a,b,c)
where語句
索引使用情況
where a=3
awhere a=3 and b=5
a,bwhere a=3 and b=5 and c=4
a,b,c
where b=3或者where b=3 and c=4或者where c=4
沒有where a=3 and c=5
awhere a=3 and b>4 and c=5
a,bwhere a=3 and b like 『kk%』 and c=4
a,b,c
where a=3 and b like 『%kk』 and c=4
awhere a=3 and b like 『%kk%』 and c=4
awhere a=3 and b like 『k%kk%』 and c=4
a,b,c
乙個VUE的小案例
商品列表 router link router link to newslist 新聞列表 router link br router view router view div body script 1.定義好元件 const newslistcomponent vue.extend const ...
乙個索引引發的問題
215 上了乙個大表的組合索引,引發了查詢sql的執行計畫混亂,最終cpu充到100 業務系統掛掉,庫也幾乎宕掉。1,為什麼建了索引後,oracle執行計畫會亂掉,而且選擇了乙個最慢的執行計畫?dba答覆 表關聯!關聯表越多,oracle選擇執行計畫出錯的概率變大!如何防止此類事件 上索引之前,先固...
乙個差分計算的案例
今天碰到乙個需求需要做趨勢分析,後來在高人指點下使用移動差分函式進行處理。雖然使用這個函式,但是要計算出來還是比較複雜的。建立測試表 create multiset table sxedrm2.test stddev pop no before journal no after journal de...