Oracle预估的基数算法

SQL> create table t as select * from dba_objects;  
  
Table created.  
  
SQL> create index idx_t on t(object_id);  
  
Index created.  


SQL> BEGIN  
  2    DBMS_STATS.GATHER_TABLE_STATS(ownname          => 'TEST',  
  3                                  tabname          => 'T',  
  4                                  estimate_percent => 100,  
  5                                  method_opt       => 'for all columns size auto',  
  6                                  degree           => DBMS_STATS.AUTO_DEGREE,  
  7                                  cascade          => TRUE);  
  8  END;  
  9  /  


SQL> alter session set optimizer_features_enable='9.2.0';

Session altered.


SQL> explain plan for  select owner from t where object_id<1000;  

Explained.

SQL> select * from table(dbms_xplan.display());

PLAN_TABLE_OUTPUT
------------------------------------------------------------------------------------------------------------------------------------------------------------

--------------------------------------------
Plan hash value: 1594971208

---------------------------------------------------------------------
| Id  | Operation		    | Name  | Rows  | Bytes | Cost  |
---------------------------------------------------------------------
|   0 | SELECT STATEMENT	    |	    |	958 | 10538 |	 26 |
|   1 |  TABLE ACCESS BY INDEX ROWID| T     |	958 | 10538 |	 26 |
|*  2 |   INDEX RANGE SCAN	    | IDX_T |	958 |	    |	  4 |
---------------------------------------------------------------------

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

   2 - access("OBJECT_ID"<1000)

Note
-----
   - cpu costing is off (consider enabling it)

18 rows selected.


那么这个958 Oracle是怎么估算的呢?
Oracle预估的基数等于有效选择性*(num_rows-num_nulls)

其中 有效选择性 ,< 的有效选择性算法为:

(limit-low_value)/(high_value-low_value)




set linesize 200
SQL> select b.num_rows,
       a.num_distinct,
       a.num_nulls,
       utl_raw.cast_to_number(high_value) high_value,
       utl_raw.cast_to_number(low_value) low_value,
       (b.num_rows - a.num_nulls) "NUM_ROWS-NUM_NULLS",
       utl_raw.cast_to_number(high_value) -
       utl_raw.cast_to_number(low_value) "HIGH_VALUE-LOW_VALUE"
  from dba_tab_col_statistics a, dba_tables b
 where a.owner = b.owner
   and a.table_name = b.table_name
   and a.owner = 'TEST'
   and a.table_name = upper('T')
   and a.column_name = 'OBJECT_ID';  2    3    4    5    6    7    8    9   10   11   12   13   14  

  NUM_ROWS NUM_DISTINCT  NUM_NULLS HIGH_VALUE  LOW_VALUE NUM_ROWS-NUM_NULLS HIGH_VALUE-LOW_VALUE
---------- ------------ ---------- ---------- ---------- ------------------ --------------------
     73964	  73964 	 0	77085	       2	      73964		   77083


那么估算为:
SQL> 
select ceil((1000-2)/77083*73964) from dual;SQL> 

CEIL((1000-2)/77083*73964)
--------------------------
		       958

Oracle 就是根据这个算法的

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

scan724

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值