PARAMETERS IN OPT_PARAM HINT
****************************
***************************************
接下来的一部分是sql语句中引用到的对象基本信息,包括关联表和各个自索引的信息,这些信息是在相关视图里面可以找到的,比如user_tables,user_indexes,这些值在cbo计算代价的时候
都会被考虑到。
BASE STATISTICAL INFORMATION
***************************************
BASE STATISTICAL INFORMATION
***********************
Table Stats::
Table: T1 Alias: T1 (NOT ANALYZED)
#Rows: 1389 #Blks: 17 AvgRowLen: 100.00
Column (#1): X(NUMBER) NO STATISTICS (using defaults)
AvgLen: 13.00 NDV: 43 Nulls: 0 Density: 0.023038
***********************
Table Stats::
Table: T Alias: T
#Rows: 50741 #Blks: 78 AvgRowLen: 4.00
Column (#1): X(NUMBER)
AvgLen: 5.00 NDV: 50741 Nulls: 0 Density: 1.9708e-05 Min: 6 Max: 50727
Index Stats::
Index: IND_T Col#: 1
LVLS: 1 #LB: 112 #DK: 50741 LB/K: 1.00 DB/K: 1.00 CLUF: 78.00
***************************************
我们看到这里一共列出3个对象的信息,它们分别是T1表,T表,T表的索引IND_T,T表的索引IND_T。
表信息的部分中包括了表的行数、数据块数、平均行数。对于字段,只列出了谓词条件中包含的字段。对于在谓词中没有出现的字段,因为它不影响执行计划的选择,所以以CBO不需要将他考虑到代价中,我们看到,这里列出的是X字段,因为它既是两表关联的字段,同时自身也是一个谓词条件,X列的信息包括了它的类型、平均长度、非重复的值、空值、密度以及列的最大最小值,这些信息在CBO做执行计划代价的计算上都要作为输入的值。
索引项部分中列出了所以的高度,索引页块数(LB,Leaf Blocks),每个索引占据的数据块数(LB/K Leaf Blocks/Key),每个索引键值对应的表中数据块(DB/K,Data Blocks/Key),索引的聚合因子(CLUF,Clustering Factor)。
要注意集合因子CLUF(索引聚合因子),它表示索引中的键值和元表中的数据分布的一种关系,当索引键值和表中数据的排列顺序大致相同时,它意味着键值指向的数据块越多时(数据排序和索引相差越大)时,这个因子就越大,越不利于索引的使用。了解这个指标对于我们分析sql的执行计划很有用处,比如我们发现SQL执行计划异常,可是从cardinality上无法解释,也许应该考虑一下是否是CLUF的影响导致的。
下面这个例子说明CLUF是如果影响CBO的成本的。
------------------------------------示例开始---------------------------------------------------
[sql] view plaincopy
SQL> create table t as select object_id,object_name from dba_objects;
Table created.
SQL> create index t_ind on t(object_id) ;
Index created.
SQL> create table t1 as select * from t where rownum=1;
Table created.
SQL> alter table t1 minimize records_per_block; --分布在更多的数据块上
Table altered.
SQL> insert into t1 select * from t;
50659 rows created.
SQL> commit;
Commit complete.
SQL> create index t1_ind on t1(object_id);
Index created.
SQL> exec SYS.DBMS_STATS.GATHER_TABLE_STATS (user,'t',Cascade=> TRUE)
PL/SQL procedure successfully completed.
SQL> exec SYS.DBMS_STATS.GATHER_TABLE_STATS (user,'t1',Cascade=> TRUE);
PL/SQL procedure successfully completed.
SQL> select table_name,num_rows,blocks from user_tables where table_name in ('T','T1');
TABLE_NAME NUM_ROWS BLOCKS
------------------------------ ---------- ----------
T 50659 239
T1 50660 25335
我们创建了两张结构和数据相同的表T和T1,其中T1的数据分布在更多的数据块上
[sql] view plaincopy
SQL> col TABLE_NAME for a10
SQL> col INDEX_NAME for a20
SQL> col NUM_ROWS for 999999
SQL> col LEAF_BLOCKS for 9999999
SQL> col CLUSTERING_FACTOR for 9999999
SQL> select table_name,index_name,num_rows,leaf_blocks,clustering_factor from user_indexes where table_name in ('T','T1');
TABLE_NAME INDEX_NAME NUM_ROWS LEAF_BLOCKS CLUSTERING_FACTOR
---------- -------------------- -------- ----------- ---------