oraunix 发表于 2010-11-15 21:58:51

Oracle执行计划中的and_equal

and_equal是Oracle支持的一种特定操作,可以将多个单列索引进行合并(Index Merge)输出查询结果。
同时and_equal可以通过Hints来进行强制,最少指定两个索引,最多指定5个。
以下的执行计划是常见的and_equal执行方式:
SQL> select /*+ and_equal(t1 iu ii) */username,password from t1 where username='EYGLE' and user_id=58;
USERNAME                     PASSWORD
------------------------------ ------------------------------
EYGLE                        B726E09FE21F8E83

执行计划
----------------------------------------------------------
Plan hash value: 1425017857
------------------------------------------------------------------------------------
| Id| Operation                   | Name | Rows| Bytes | Cost (%CPU)| Time   |
------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |      |   1 |    47 |   2   (0)| 00:00:01 |
|*1 |TABLE ACCESS BY INDEX ROWID| T1   |   1 |    47 |   2   (0)| 00:00:01 |
|   2 |   AND-EQUAL               |      |       |       |            |          |
|*3 |    INDEX RANGE SCAN         | II   |   1 |       |   1   (0)| 00:00:01 |
|*4 |    INDEX RANGE SCAN         | IU   |   1 |       |   1   (0)| 00:00:01 |
------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
   1 - filter("USERNAME"='EYGLE' AND "USER_ID"=58)
   3 - access("USER_ID"=58)
   4 - access("USERNAME"='EYGLE')
但是从Oracle 10g开始,and_equal操作被废弃(depricated)掉,Oracle不再支持。这里废弃的含义并不是被彻底移除,而是说不再进行改进,通过hints仍然可以强制实现Index Merge的and_equal操作。
以上的输出就是来自Oracle 10.2.0.4,在使用rule提示时,Oracle会主动选择and_equal,所以不再支持是因为,这种方法限制过多,而且远不如复合索引来的灵活:
SQL> select * from v$version;
BANNER
----------------------------------------------------------------
Oracle Database 10g Enterprise Edition Release 10.2.0.4.0 - Prod
PL/SQL Release 10.2.0.4.0 - Production
CORE    10.2.0.4.0      Production
TNS for 32-bit Windows: Version 10.2.0.4.0 - Production
NLSRTL Version 10.2.0.4.0 - Production

SQL> select /*+ rule */username,password from t1 where username='EYGLE' and user_id=58;
USERNAME                     PASSWORD
------------------------------ ------------------------------
EYGLE                        B726E09FE21F8E83

执行计划
----------------------------------------------------------
Plan hash value: 3072843751
--------------------------------------------
| Id| Operation                   | Name |
--------------------------------------------
|   0 | SELECT STATEMENT            |      |
|   1 |TABLE ACCESS BY INDEX ROWID| T1   |
|   2 |   AND-EQUAL               |      |
|*3 |    INDEX RANGE SCAN         | IU   |
|*4 |    INDEX RANGE SCAN         | II   |
--------------------------------------------
新的可选替代方案是NDEX_COMBINE,从9i开始,初始化参数 _b_tree_bitmap_plans设置为true,允许为B*Tree索引使用,bitmap convert:
SQL> select /*+ index_combine(t1 iu ii) */username,password from t1 where username='EYGLE' and user_id=58;
USERNAME                     PASSWORD
------------------------------ ------------------------------
EYGLE                        B726E09FE21F8E83

执行计划
----------------------------------------------------------
Plan hash value: 1808973554
-----------------------------------------------------------------------------------------
| Id| Operation                        | Name | Rows| Bytes | Cost (%CPU)| Time   |
-----------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT               |      |   1 |    47 |   2   (0)| 00:00:01 |
|   1 |TABLE ACCESS BY INDEX ROWID   | T1   |   1 |    47 |   2   (0)| 00:00:01 |
|   2 |   BITMAP CONVERSION TO ROWIDS    |      |       |       |            |          |
|   3 |    BITMAP AND                  |      |       |       |            |          |
|   4 |   BITMAP CONVERSION FROM ROWIDS|      |       |       |            |          |
|*5 |      INDEX RANGE SCAN            | II   |       |       |   1   (0)| 00:00:01 |
|   6 |   BITMAP CONVERSION FROM ROWIDS|      |       |       |            |          |
|*7 |      INDEX RANGE SCAN            | IU   |       |       |   1   (0)| 00:00:01 |
-----------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
   5 - access("USER_ID"=58)
   7 - access("USERNAME"='EYGLE')

页: [1]
查看完整版本: Oracle执行计划中的and_equal