sql 优化过程之union 替换 or

在网上看了一些sql优化的文章,其中有一条就是使用union 替换 or。原因是在索引列上使用or,会使索引失效,从而走全表扫描。说的比较笼统,我今天特意试验了一下:在什么情况下可以用union 替换 or才会使索引生效。

create table t as select * from all_objects;

然后又在t上添加了一列id,使用object_id填充的。

create index ind_t_id on t(id);只在id上建立索引。

set autotrace traceonly

select * from t where object_id=10 or id=20;


SQL> select * from t where object_id=10 or id=20;

未选定行


执行计划
----------------------------------------------------------
Plan hash value: 1601196873

--------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 9 | 1539 | 229 (1)| 00:00:03 |
|* 1 | TABLE ACCESS FULL| T | 9 | 1539 | 229 (1)| 00:00:03 |
--------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

1 - filter("OBJECT_ID"=10 OR "ID"=20)

Note
-----
- dynamic sampling used for this statement


统计信息
----------------------------------------------------------
0 recursive calls
0 db block gets
815 consistent gets
0 physical reads
0 redo size
1176 bytes sent via SQL*Net to client
405 bytes received via SQL*Net from client
1 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
0 rows processed
这种情况下索引失效。

select * from t where object_id=10

union

select * from id=20;

SQL> select * from t where object_id=10
2 union
3 select * from t where id=20;

未选定行


执行计划
----------------------------------------------------------
Plan hash value: 298853808

--------------------------------------------------------------------------------
----------

| Id | Operation | Name | Rows | Bytes | Cost (%CPU)|
Time |

--------------------------------------------------------------------------------
----------

| 0 | SELECT STATEMENT | | 10 | 1710 | 231 (2)|
00:00:03 |

| 1 | SORT UNIQUE | | 10 | 1710 | 231 (2)|
00:00:03 |

| 2 | UNION-ALL | | | | |
|

|* 3 | TABLE ACCESS FULL | T | 9 | 1539 | 228 (1)|
00:00:03 |

| 4 | TABLE ACCESS BY INDEX ROWID| T | 1 | 171 | 1 (0)|
00:00:01 |

|* 5 | INDEX RANGE SCAN | IND_T_ID | 1 | | 1 (0)|
00:00:01 |

--------------------------------------------------------------------------------
----------


Predicate Information (identified by operation id):
---------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

3 - filter("OBJECT_ID"=10)
5 - access("ID"=20)

Note
-----
- dynamic sampling used for this statement


统计信息
----------------------------------------------------------
13 recursive calls
0 db block gets
958 consistent gets
0 physical reads
0 redo size
1176 bytes sent via SQL*Net to client
405 bytes received via SQL*Net from client
1 SQL*Net roundtrips to/from client
1 sorts (memory)
0 sorts (disk)
0 rows processed

可以发现union替换or之后,索引生效。

然后我在object_id上建立索引,再看看情况是什么样的:

create index ind_t on t(object_id);

select * from t where object_id=10 or id=20;

SQL> select * from t where object_id=10 or id=20;

未选定行


执行计划
----------------------------------------------------------
Plan hash value: 3010370457

--------------------------------------------------------------------------------
-------------

| Id | Operation | Name | Rows | Bytes | Cost (%CPU
)| Time |

--------------------------------------------------------------------------------
-------------

| 0 | SELECT STATEMENT | | 9 | 1539 | 148 (0
)| 00:00:02 |

| 1 | TABLE ACCESS BY INDEX ROWID | T | 9 | 1539 | 148 (0
)| 00:00:02 |

| 2 | BITMAP CONVERSION TO ROWIDS | | | |
| |

| 3 | BITMAP OR | | | |
| |

| 4 | BITMAP CONVERSION FROM ROWIDS| | | |
| |

|* 5 | INDEX RANGE SCAN | IND_T | | | 1 (0
)| 00:00:01 |

| 6 | BITMAP CONVERSION FROM ROWIDS| | | |
| |

|* 7 | INDEX RANGE SCAN | IND_T_ID | | | 1 (0
)| 00:00:01 |

--------------------------------------------------------------------------------
-------------

可以发现这种情况下,即使使用了or,索引还是有效地。

当然这种情况使用union也是索引有效地。

结论:

有索引和无索引的一列 进行or连接时。使用union替换or会使索引生效。而两列都有索引时。or和union都是可以使用索引的。

[@more@]

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/22418990/viewspace-1054729/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/22418990/viewspace-1054729/

你可能感兴趣的:(sql 优化过程之union 替换 or)