10G的时候
SQL> select * from v$version where rownum=1;
BANNER
----------------------------------------------------------------
Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - Prod
SQL> select num_rows from user_tables where table_name='WXH_TBD1';
NUM_ROWS
----------
200000
explain plan for
select * from wxh_tbd1 where object_id>:a;
SQL> select * from table(dbms_xplan.display);
PLAN_TABLE_OUTPUT
-----------------------------------------------
Plan hash value: 1038246325
-----------------------------------------------
| Id | Operation | Name | Rows |
-----------------------------------------------
| 0 | SELECT STATEMENT | | 10000 |
|* 1 | TABLE ACCESS FULL| WXH_TBD1 | 10000 |
-----------------------------------------------
explain plan for
select * from wxh_tbd1 where object_id>:a and object_id<:b;
SQL> select * from table(dbms_xplan.display);
PLAN_TABLE_OUTPUT
-----------------------------------------------
Plan hash value: 1744766238
-----------------------------------------------
| Id | Operation | Name | Rows |
-----------------------------------------------
| 0 | SELECT STATEMENT | | 500 |
|* 1 | FILTER | | |
|* 2 | TABLE ACCESS FULL| WXH_TBD1 | 500 |
-----------------------------------------------
10G都是对的,开区间的时候,10000/200000=5%,闭区间的时候,500/200000=5%*5%,都是正确的。
看看11G
select * from v$version where rownum=1;
BANNER
--------------------------------------------------------------------------------
Oracle Database 11g Enterprise Edition Release 11.1.0.7.0 - 64bit Production
select num_rows from user_tables where table_name='WXH_TBD';
NUM_ROWS
----------
19366
explain plan for
select * from wxh_tbd where object_id>:A;
Explained.
select * from table(dbms_xplan.display);
PLAN_TABLE_OUTPUT
------------------------------------------------------------------------------------------------------------------------------------------------------
Plan hash value: 3295978849
-----------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-----------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 966 | 89838 | 144 (3)| 00:00:01 |
|* 1 | TABLE ACCESS FULL| WXH_TBD | 966 | 89838 | 144 (3)| 00:00:01 |
-----------------------------------------------------------------------------
966/19366=5%,是OK的。
explain plan for
select * from wxh_tbd where object_id>:A AND OBJECT_ID<:B;
select * from table(dbms_xplan.display);
------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 966 | 89838 | 144 (3)| 00:00:01 |
|* 1 | FILTER | | | | | |
|* 2 | TABLE ACCESS FULL| WXH_TBD | 966 | 89838 | 144 (3)| 00:00:01 |
------------------------------------------------------------------------------
我们看到没变化。
还是966.看来11G以后不管是开区间还是闭区间,都是默认的5%了,而不会像以前那样相乘了。(都是绑定变量的情况)
select /*+ index(wxh_tbd) */ object_name from wxh_tbd where object_id > :a;
-------------------------------------------------------
| Id | Operation | Name | Rows |
-------------------------------------------------------
| 0 | SELECT STATEMENT | | 2492 |
| 1 | TABLE ACCESS BY INDEX ROWID| WXH_TBD | 2492 |
|* 2 | INDEX RANGE SCAN | PK_N | 449 |
-------------------------------------------------------
2 - access("OBJECT_ID">TO_NUMBER(:A))
最终表的选择率是5%。2492/49842=5%.
可是索引的基数449不知道咋算的,没查到资料,让人摸不到头脑,不按套路来
非绑定变量的情况下的选择性和基数都是可以算出来的。我只是不知道这个开区间,绑定变量的情况下,索引如何去计算的这个选择性和基数。
explain plan for select /*+ index(wxh_tbd1 T_1) */ object_name from wxh_tbd1 where object_id >12345;
select * from table(dbms_xplan.display);
--------------------------------------------------------
| Id | Operation | Name | Rows |
--------------------------------------------------------
| 0 | SELECT STATEMENT | | 17913 |
| 1 | TABLE ACCESS BY INDEX ROWID| WXH_TBD1 | 17913 |
|* 2 | INDEX RANGE SCAN | T_1 | 17913 |
--------------------------------------------------------
这种非绑定变量的情况,我是可以算出来的。
select min(object_id) from wxh_tbd1;
MIN(OBJECT_ID)
--------------
2
select max(object_id) from wxh_tbd1;
MAX(OBJECT_ID)
--------------
159398
select count(*) from wxh_tbd1;
COUNT(*)
----------
19463
SELECT column_name,NUM_NULLS FROM USER_TAB_COLS WHERE TABLE_NAME='WXH_TBD1' and column_name='OBJECT_ID';
COLUMN_NAME NUM_NULLS
-------------------- ----------
OBJECT_ID 47
选择率=(最大值-开区间值)/最大值
基数=选择率*总行数(非空)
select ((159398-12345)/159398)*(19463-47) FROM DUAL;
((159398-12345)/159398)*(19463-47)
----------------------------------
17912.2765
可以看到最后计算的结果跟ORACLE计算出来的是一样的。
只是不知道开区间绑定变量的情况,ORACLE是怎么计算的。
[ 本帖最后由 wei-xh 于 2011-6-13 10:04 编辑 ]
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/22034023/viewspace-697788/ ,如需转载,请注明出处,否则将追究法律责任。