--導(dǎo)致查詢緩慢的原因,主要有以下幾點(diǎn)
? ? 1活逆、數(shù)據(jù)量過大
? ? 2精刷、表設(shè)計(jì)不合理
? ? 3、sql語句寫得不好蔗候,引起全表掃描怒允,索引失效
? 我們這里主要對(duì)第三種引起全表掃描的sql的情況進(jìn)行分析
? 對(duì)查詢進(jìn)行優(yōu)化,應(yīng)盡量避免全表掃描锈遥,那么常見哪些情況下sql查詢會(huì)出現(xiàn)不走索引的情況误算,參考網(wǎng)上的資料仰美,這里做一個(gè)總結(jié),最后再講一些sql優(yōu)化的小技巧
? 1.模糊匹配like的情況
? 索引字段使用like的時(shí)候儿礼,唯有后置like即like 'XXX'||'%'這種情況繼續(xù)走索引咖杂,左模糊like
‘%...’無法直接使用索引,但可以利用reverse + function index 的形式蚊夫,變化成 like ‘…%’诉字;全模糊是無法優(yōu)化的,一定要的話考慮用搜索引擎知纷。出于降低數(shù)據(jù)庫服務(wù)器的負(fù)載考慮壤圃,盡可能地減少數(shù)據(jù)庫模糊查詢。
? ? 2. 查詢條件使用了(<>琅轧、!=)
? ? SQL中伍绳,不等于操作符會(huì)限制索引,引起全表掃描乍桂,即使比較的字段上有索引,可以考慮將條件用or拆分開即(字段<值 or 字段>值)
? ? 3. or使用注意項(xiàng)
? ? 使用or的時(shí)候需要注意冲杀,where子句中比較的兩個(gè)條件,一個(gè)有索引睹酌,一個(gè)沒索引嘀倒,使用or則會(huì)引起全表掃描之景,例如:where A=:1 or B=:2慧库,A上有索引季稳,B上沒索引,則比較B=:2時(shí)會(huì)重新開始全表掃描
? ? 4. is null
? ? 查詢字段is null時(shí)單索引失效辐啄,引起全表掃描采章,對(duì)于is null 字段如果需要索引,可以考慮與一個(gè)非null字段組成聯(lián)合索引壶辜,這樣可以啟用索引查找悯舟;is not null 時(shí)永遠(yuǎn)不會(huì)使用索引。一般數(shù)據(jù)量大的表不要用is null查詢士复。
? ? 5. 聯(lián)合索引
聯(lián)合索引的情況缺少前導(dǎo)列,只有后導(dǎo)列翩活,會(huì)引起全表掃描阱洪,例create index iss on student(name,school)時(shí),select count(1)from student where school='XX'會(huì)全表掃描菠镇,可以通過強(qiáng)制索引在缺少前置索引的情況下走索引 冗荸,如 select /*+index(student iss)count(1)from student where school='XX'
? ? 6. in和 not in
in 和not in 也要慎用,否則會(huì)導(dǎo)致全表掃描利耍,?如: select id from t where num in(1,2,3)? 對(duì)于連續(xù)的數(shù)值蚌本,能用between 就不要用in 了: select id from t where num between 1 and 3
很多時(shí)候用exists 代替in 是一個(gè)好的選擇:
?select num from a where num in(select num from b)
?用下面的語句替換:
? select num from a where exists(select 1 from b where num=a.num)
? exists執(zhí)行順序:1.首先執(zhí)行一次外部查詢 2.執(zhí)行一次內(nèi)部查詢盔粹,exists 非null返回true 3.遍歷外表得到查詢結(jié)果
? ? 7. where 字句對(duì)字段進(jìn)行操作
?select id from t where num/2=100 ,不走索引程癌,select id from t where num=100*2 走索引
tips:
? 1. where A=:A and B=:B 執(zhí)行時(shí)是從右往左執(zhí)行舷嗡,所以盡量把過濾條件大的放在右邊
? 2.select * from 表,需要先查詢字典嵌莉,將*解析成字段进萄,增加額外開銷,所以select 后面應(yīng)盡量寫出需要的字段
? 3.盡量使用數(shù)字型字段锐峭,若只含數(shù)值信息的字段盡量不要設(shè)計(jì)為字符型中鼠,這會(huì)降低查詢和連接的性能,并會(huì)增加存儲(chǔ)開銷
? 4. 盡可能的使用varchar/nvarchar 代替char/nchar 沿癞,因?yàn)槭紫茸冮L字段存儲(chǔ)空間小援雇,可以節(jié)省存儲(chǔ)空間,其次對(duì)于查詢來說椎扬,在一個(gè)相對(duì)較小的字段內(nèi)搜索效率顯然要高些
? 5. 數(shù)字值的字符型字段惫搏,查詢時(shí)最好對(duì)條件值進(jìn)行字符話,不要直接寫數(shù)字盗舰,否則會(huì)進(jìn)行強(qiáng)制轉(zhuǎn)換晶府,增加開銷