一些常見的SQL優(yōu)化
-
負向條件查詢不能使用索引
select * from order where status!=0 and stauts!=1 not in/not exists都不是好習慣 可以優(yōu)化為in查詢: select * from order where status in(2,3) -
前導(dǎo)模糊查詢不能使用索引
select * from order where desc like '%XX' 而非前導(dǎo)模糊查詢則可以: select * from order where desc like 'XX%' -
數(shù)據(jù)區(qū)分度不大的字段不宜使用索引
select * from user where sex=1 原因:性別只有男,女,每次過濾掉的數(shù)據(jù)很少,不宜使用索引。 經(jīng)驗上,能過濾80%數(shù)據(jù)時就可以使用索引。對于訂單狀態(tài),如果狀態(tài)值很少, 不宜使用索引,如果狀態(tài)值很多,能夠過濾大量數(shù)據(jù),則應(yīng)該建立索引。 -
在屬性上進行計算不能命中索引
select * from order where YEAR(date) < = '2017' 即使date上建立了索引,也會全表掃描,可優(yōu)化為值計算: select * from order where date < = CURDATE() 或者: select * from order where date < = '2017-01-01' -
允許為null的列,查詢有潛在大坑
單列索引不存null值,復(fù)合索引不存全為null的值,如果列允許為null, 可能會得到“不符合預(yù)期”的結(jié)果集 select * from user where name != 'shenjian' 如果name允許為null,索引不存儲null值,結(jié)果集中不會包含這些記錄。 所以,請使用not null約束以及默認值。 -
復(fù)合索引最左前綴,并不是值SQL語句的where順序要和復(fù)合索引一致
用戶中心建立了(login_name, passwd)的復(fù)合索引 select * from user where login_name=? and passwd=? select * from user where passwd=? and login_name=? 都能夠命中索引 select * from user where login_name=? 也能命中索引,滿足復(fù)合索引最左前綴 select * from user where passwd=? 不能命中索引,不滿足復(fù)合索引最左前綴 -
使用ENUM而不是字符串
ENUM保存的是TINYINT,別在枚舉中搞一些“中國”“北京”“技術(shù)部”這樣的字符串,字符串空間又大,效率又低。 -
如果明確知道只有一條結(jié)果返回,limit 1能夠提高效率
select * from user where login_name=? 可以優(yōu)化為: select * from user where login_name=? limit 1 原因: 你知道只有一條結(jié)果,但數(shù)據(jù)庫并不知道,明確告訴它,讓它主動停止游標移動