like查詢索引失效問題與解決辦法

2021-09-17 05:33:51 字數 3056 閱讀 2352

一.like查詢與索引

在oracle裡的乙個超級大的表中,我們的where條件的列有建索引的話,會走索引唯一掃瞄index unique scan。如select * from table where code = 'cod25',而如下這些語句哪些會走索引呢?

sql**  

select * from table where code like 'code2%'  

select * from table where code like '%ode2%'  

select * from table where code like '%ode2'

經驗證:select * from table where code like 'cod2%'會走索引,且走的是index range scan,而這樣寫like '%***'或'%***%'不會走索引,感覺就像組合索引一樣,直接用索引第乙個欄位會走索引,而用索引第二個欄位則不會走索引。

當然,如果select * from table where code like 'cod%' 查詢的結果就是所有記錄,走索引和full table scan的結果是一樣的,所以也將是全表掃瞄。可以換成select * from table where code like 'code2%'或者 select count(*) from table where code like 'cod%'試試,應該不會是全表掃瞄。

二.優化like查詢

1.經上面測試,like查詢結果如下:

a.like %keyword    索引失效,使用全表掃瞄。但可以通過翻轉函式+like前模糊查詢+建立翻轉函式索引=走翻轉函式索引,不走全表掃瞄。如where reverse(code) like reverse('%code2')

b.like keyword%    索引有效。  

c.like %keyword%   索引失效,也無法使用反向索引。

2.優化like查詢:

a.使用其它函式來進行模糊查詢,如果出現的位置大於0,表示包含該字串,查詢效率比like要高。

1)在oracle中,可以用instr,這樣查詢效果很好,速度很快。

sql**  

select count(*) from table t where instr(t.code,'cod2%') > 0
2)在mysql中,可以用locate和position函式,如table.field like '%aaa%'可以改為locate('aaa', table.field) > 0或position('aaa' in table.field)>0。

locate(substr,str)、position(substr in str):返回子串 substr 在字串 str 中第一次出現的位置。如果子串 substr 在 str 中不存在,返回值為 0。

3)在sql server中,可以給字段建立全文索引,用contains來檢索資料,contains用法,可以參考:

b.查詢%xx的記錄  

sql**  

select count(c.c_ply_no) as count  

from policy_data_all c, item_data_all i  

where c.c_ply_no = i.c_ply_no  

and i.c_lcn_no like 』%245′

在執行的時候,執行計畫顯示,消耗值,io值,cpu值均非常大,原因是like後面前模糊查詢導致索引失效,進行全表掃瞄。

解決方法:這種只有前模糊的sql可以改造如下寫法

sql**  

select count(c.c_ply_no) as count  

from policy_data_all c, item_data_all i  

where c.c_ply_no = i.c_ply_no  

and reverse(i.c_lcn_no) like reverse('%245')

使用翻轉函式+like前模糊查詢+建立翻轉函式索引=走翻轉函式索引,不走全掃瞄。有效降低消耗值,io值,cpu值這三個指標,尤其是io值的降低。

建函式索引:create index p_idx on table(instr(code,'code2'));需進一步說明的是,這樣的話,只有where instr(code,'code2')才會走index range scan,其它如where instr(code, 'code3')會走index fast full scan甚至table access full。

另外,select * from table where upper(code) = 'abcd',會走table access full。如果建函式索引create index idx_upper on table(upper(code));之後,將會是index range scan,如下所示:

ps:一般索引和函式索引的區別

1.一般的索引:

sql** 

create index p_idx on table1(column1);
當執行select * from table1 where column1 = ***時會用到索引。

2.函式索引:

sql**  

create index p_idx on table1(substr(column1,0,5));
當執行select * from table1 where substr(column1,0,5) = *** 時會用到索引。但執行select * from table1 where column1 = ***時是不會用到索引的。一般情況下是最好不用建函式索引。

like查詢與索引

一.like查詢與索引 在oracle裡的乙個超級大的表中,我們的where條件的列有建索引的話,會走索引唯一掃瞄index unique scan。如select from table where code cod25 而如下這些語句哪些會走索引呢?sql select from table wh...

like索引失效原因 索引失效的情況及原因定位

同事遇到乙個奇葩的問題,乙個表裡某個欄位建了索引,但是有的值走索引,有的值不走索引。因為一般情況乙個字段要麼完全不走索引,要麼走索引,怎麼會有的值走索引,有的不走索引。select 條件非常簡單,因為涉及到敏感資訊就不貼表結構了。例如select from order where status 2 ...

mysql模糊查詢索引失效問題及解決方案

我們在使用like 萬用字元時常常會引起索引失效的問題。這裡,我們討論一下like使用 的幾種情況 下列例子用到的索引 vc student name 一 like xx explain select from t student where vc student name like 王 二 lik...