1. 程式人生 > 實用技巧 >由淺入深學優化之like‘%%’坑爹寫法

由淺入深學優化之like‘%%’坑爹寫法

某交易系統,監控告警有長SQL產生,指令碼查詢大於5分鐘的長SQL。指令碼內容如下:
SQL Text : select from ( select tmp_page., rownum row_id from ( SELECT
UUID,USR_ID,IN_MNO,MNO,xxxx,xxx,xxx,xxxxx,xxxxx
FROM ABC.MEC_IF
WHERE MNO LIKE :1
order by UUID desc ) tmp_page where rownum <= :2 ) where
row_id > :3

Bind Variables :
1 - (VARCHAR2(128)):%836305057320133%

2 - (NUMBER):20
3 - (NUMBER):0

MNO like欄位內容很長嗎?

15:09:16 [email protected](bapdb1)> SELECT mno from BAP.T_BAP_MEC_IF where rownum<=2;

MNO

500591001000000
500591001000001
是不是很蛋有點疼,興許開發大爺心情不爽,非要搞事情。耐心看一下執行計劃,丫肯定走偏了。
由淺入深學優化之like‘%%’坑爹寫法

該表的PK是UUID列,MNO列也有自己的索引,最爛的執行計劃,索引全掃描外加回表,由於受ORDER BY UUID DESC影響,oracle錯誤的選擇了index掃描

由淺入深學優化之like‘%%’坑爹寫法
由淺入深學優化之like‘%%’坑爹寫法

當一個列出現在where條件中,該列沒有建立索引,並且選擇性大於20%,那麼該列就必須建立索引

其實此類SQL優化起來比較簡單
EXPLAIN PLAN FOR select from ( select tmp_page., rownum row_id from ( SELECT
UUID,USR_ID,IN_MNO,MNO,xxxx,xxx,xxx,xxxxx,xxxxx
FROM ABC.MEC_IF
WHERE MNO LIKE '836305057320133%'
order by UUID desc ) tmp_page where rownum <= 20 ) where
row_id > 0;
由淺入深學優化之like‘%%’坑爹寫法

1。儘量不要使用 like '%%'
2。對於 like '%' (不以 % 開頭),Oracle可以應用 colunm上的index

3。對於 like '%…' 的 (不以 % 結尾),可以利用reverse + function index 的形式,變化成 like '%'
4.非用like'%%'不可時,使用Oracle內部函式:INSTR()解決。
例子:select * from emp where instr(job,'RE')>0 and instr(ename,'A')>0 and instr(mgr,'3')>0;

轉載於:https://blog.51cto.com/yangjunfeng/2146052