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> select leaf_blocks,blevel,clustering_factor from dba_indexes where index_name='IDX_T';  

LEAF_BLOCKS	BLEVEL CLUSTERING_FACTOR
----------- ---------- -----------------
	165	     1		    1705



LEAF_BLOCKS 叶子块 165个

BLEVEL  索引高度-1


集群因子;
CLUSTERING_FACTOR =1705


SQL> select count(distinct dbms_rowid.rowid_block_number(rowid)) from T;

COUNT(DISTINCTDBMS_ROWID.ROWID_BLOCK_NUMBER(ROWID))
---------------------------------------------------
					       1057

存储在1057个块中

SQL> 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
---------- ------------ ---------- ---------- ---------- ------------------ --------------------
     74486	  74486 	 0	77616	       2	      74486		   77614



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 (%CPU)| Time     |
-------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT	    |	    |	958 | 10538 |	 26   (0)| 00:00:01 |
|   1 |  TABLE ACCESS BY INDEX ROWID| T     |	958 | 10538 |	 26   (0)| 00:00:01 |
|*  2 |   INDEX RANGE SCAN	    | IDX_T |	958 |	    |	  4   (0)| 00:00:01 |
-------------------------------------------------------------------------------------

Predicate Information (identified by operation id):

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

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

   2 - access("OBJECT_ID"<1000)

14 rows selected.


索引扫描首先要定义到叶子块:


定位到叶子块 要扫描 多少个块???  需要高度-1个块

叶子块个数 乘以 选择性

定位到叶子块 要扫描 多少个块???

回表和集群因子有关:

选择性(Selectivity) 列唯一键(Distinct_Keys) 与行数(Num_Rows)的比值。


这里有个概念叫有效选择性 ,< 的有效选择性为

(limit-low_value)/(high_value-low_value)


limit 是限制
1000

low_value=2

1000-2 有可能扫到的值的范围


high_value-low_value  表示总共有多少个值:

HIGH_VALUE=77616

LOW_VALUE=2

HIGH_VALUE-LOW_VALUE=77614

LEAF_BLOCKS=165


索引扫描的计算公式如下:
cost =  
 blevel +  
 celiling(leaf_blocks *effective index selectivity) +  
 celiling(clustering_factor * effective table selectivity)


SQL> select 1+ceil(165*(1000-2)/77614)+ceil(1705*(1000-2)/77614) from dual; 

1+CEIL(165*(1000-2)/77614)+CEIL(1705*(1000-2)/77614)
----------------------------------------------------
						  26


为啥effective table selectivity和effective index selectivity一样?

表和索引都包含指定列的数据 两者当然一样




你可能感兴趣的:(Oracle索引扫描算法)