在oracle中对于like操作时,如果是前后都是模糊查询的时候(类似于col01 like ‘%xxx%’)是没有办法用到索引的,这里提供一种对于这种情况的优化思路,主要的思路是把大表变小,把查询的实体表变窄,把需要的数据放到索引里.
常规的写法:
create table t01 as select * from dba_objects;
SQL> create index t01_01
on t01(object_name);
|
Index created.
|
SQL> set autot trace
|
SQL> select *
from t01
where object_name
like '%EMP%' ; |
176 rows selected.
|
Execution Plan |
---------------------------------------------------------- |
Plan hash value: 3295674804 |
-------------------------------------------------------------------------- |
| Id | Operation | Name |
Rows | Bytes | Cost (%CPU)|
Time |
|
-------------------------------------------------------------------------- |
| 0 | SELECT STATEMENT | | 7091 | 775K| 522 (1)| 00:00:07 | |
|* 1 | TABLE ACCESS
FULL | T01 | 7091 | 775K| 522 (1)| 00:00:07 | |
-------------------------------------------------------------------------- |
Predicate Information (identified
by operation id):
|
--------------------------------------------------- |
1 - filter( "OBJECT_NAME" LIKE
'%EMP%' )
|
Statistics |
---------------------------------------------------------- |
1 recursive calls |
0 db block gets |
2335 consistent gets |
0 physical reads |
0 redo size |
14552 bytes sent via SQL*Net to client
|
608 bytes received via SQL*Net from client
|
13 SQL*Net roundtrips to / from client
|
0 sorts (memory) |
0 sorts (disk) |
176 rows processed |
优化后的写法:
SQL> select /*+ use_nl(t01 v01) */ *
|
from t01, ( select rowid
from t01
where object_name
like '%EMP%' ) v01 |
where t01.rowid = v01.rowid;
|
176 rows selected.
|
Execution Plan |
---------------------------------------------------------- |
Plan hash value: 73453348 |
-------------------------------------------------------------------------------------- |
| Id | Operation | Name |
Rows | Bytes | Cost (%CPU)|
Time |
|
-------------------------------------------------------------------------------------- |
| 0 | SELECT STATEMENT | | 7091 | 1017K| 7241 (1)| 00:01:27 | |
| 1 | NESTED LOOPS | | 7091 | 1017K| 7241 (1)| 00:01:27 | |
|* 2 | INDEX FAST
FULL SCAN | T01_01 | 7091 | 242K| 147 (2)| 00:00:02 | |
| 3 | TABLE ACCESS
BY USER
ROWID| T01 | 1 | 112 | 1 (0)| 00:00:01 |
|
-------------------------------------------------------------------------------------- |
Predicate Information (identified
by operation id):
|
--------------------------------------------------- |
2 - filter( "OBJECT_NAME" LIKE
'%EMP%' )
|
Statistics |
---------------------------------------------------------- |
1 recursive calls |
0 db block gets |
857 consistent gets |
0 physical reads |
0 redo size |
18049 bytes sent via SQL*Net to client
|
608 bytes received via SQL*Net from client
|
13 SQL*Net roundtrips to / from client
|
0 sorts (memory) |
0 sorts (disk) |
176 rows processed |
针对于上面的例子,IO从2335降到857,用这种方法在表越宽返回记录越少时效果越好.