在网上看了一些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/