对象统计信息的作用是帮助查询优化器选择更好的执行计划。
比如,某一个表的索引clustering_factor非常的高,这个时候如果在where条件中指定column between A and B的限定条件来查询,那么查询优化器有两个选择,一个是通过索引做索引范围扫描,另一个是全表扫描。
因为我们知道clustering_factor的值非常高,这时候做索引范围扫描的开销可能还会比全表扫描更高。所以我们期望是全表扫描。
但是如果数据库中没有关于这个索引数据对象的统计信息,那么查询优化器就不会了解到这个索引的 clustering_factor很高,那么查询优化器就有可能选择索引范围扫描的执行计划,这样就会产生一个低效的执行计划。 所以我们可以看到,对象的统计信息的重要。
下面了解一下对象的统计信息。
1. 对象统计信息有哪几种类型
有三种类型的对象统计信息:表统计,列统计,索引统计。
对象 |
表/索引级别统计 |
分区级别统计 |
子分区级别统计 |
表 |
user_tab_statistics user_tables |
user_tab_statistics user_tables |
user_tab_statistics user_tables |
列 |
user_tab_col_statistics user_tab_histograms |
user_part_col_statistics user_part_histograms |
user_subpart_col_statistics user_subpart_histograms |
索引 |
user_ind_statistics user_indexes |
user_ind_statistics user_ind_partitions |
user_ind_statistics user_ind_subpartitions |
为了测试,我们创建如下表并手动搜集统计信息。
CREATE TABLE t AS SELECT ROWNUM AS id, ROUND(DBMS_RANDOM.normal*1000) AS val1, 100+ROUND(LN(ROWNUM/3.25+2)) AS val2, 100+ROUND(LN(ROWNUM/3.25+2)) AS val3, DBMS_RANDOM.string('p',250) AS pad FROM all_objects WHERE ROWNUM<=1000 ORDER BY dbms_random.value;
UPDATE t SET val1=NULL WHERE val1<0; ALTER TABLE t ADD CONSTRAINT t_pk PRIMARY KEY(id); CREATE INDEX t_val1_i ON t(val1); CREATE INDEX t_val2_i ON t(val2);
BEGIN dbms_stats.gather_table_stats( ownname => 'SYS', tabname =>'T', method_opt => 'for all columns size skewonly', cascade => TRUE); END;
|
下面详细说一下表,列,索引的统计信息。
1.1 表统计信息
表统计信息从user_tab_statistics中可以得到。
SELECT
num_rows,blocks,empty_blocks,avg_space,chain_cnt,avg_row_len
FROM
user_tab_statistics
WHERE
table_name = 'T';
这里要注意的是empty_blocks表示高水位以上的数据块,这里为0,因为dbms_stat不计算其值。Avg_space表示数据块平均空闲空间(字节),这里也不计算,设置为0。Chain_cnt 行链接和航迁移总数,也不计算设置为零。Avg_row_len table中平均行的长度(字节)。
1.2 列统计信息
列统计信息有两种,普通列统计信息和直方图。先看一下普通列统计信息。
普通列统计信息