在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,用这种方法在表越宽返回记录越少时效果越好.