Oracle基于CBO的优化器在生成执行计划时,很大程度上依赖于统计信息,你可以把CBO理解为一个复杂的数学模型,而统计信息是它最主要的输入,执行计划是输出,如果输入都不准确,输出还可能准确吗?所有,统计信息是否及时有效对执行计划的好坏有着关键的影响。
Oracle里采用dbms_stats包分析统计信息(Analyze命令已过时,不建议使用),该包的使用方法,官方文档有详细说明( http://docs.oracle.com/cd/E11882_01/appdev.112/e25788/d_stats.htm#i1036461),这里挑几个最常用的说说。
DBMS_STATS.GATHER_TABLE_STATS ( ownname VARCHAR2, tabname VARCHAR2, partname VARCHAR2 DEFAULT NULL, estimate_percent NUMBER DEFAULT NULL, block_sample BOOLEAN DEFAULT FALSE, method_opt VARCHAR2 DEFAULT 'FOR ALL COLUMNS SIZE 1', degree NUMBER DEFAULT NULL, granularity VARCHAR2 DEFAULT 'DEFAULT', cascade BOOLEAN DEFAULT FALSE, stattab VARCHAR2 DEFAULT NULL, statid VARCHAR2 DEFAULT NULL, statown VARCHAR2 DEFAULT NULL, no_invalidate BOOLEAN DEFAULT FALSE);
先说说什么是直方图,直方图是对列上的数据分布进行统计,让优化器知道数据在各个列上的分布情况,如果数据在某列上的分布很倾斜,则最好对该列收集直方图信息。
method_opt有如下选项:
DBMS_STATS.GATHER_INDEX_STATS ( ownname VARCHAR2, indname VARCHAR2, partname VARCHAR2 DEFAULT NULL, estimate_percent NUMBER DEFAULT to_estimate_percent_type (GET_PARAM('ESTIMATE_PERCENT')), stattab VARCHAR2 DEFAULT NULL, statid VARCHAR2 DEFAULT NULL, statown VARCHAR2 DEFAULT NULL, degree NUMBER DEFAULT to_degree_type(get_param('DEGREE')), granularity VARCHAR2 DEFAULT GET_PARAM('GRANULARITY'), no_invalidate BOOLEAN DEFAULT to_no_invalidate_type (GET_PARAM('NO_INVALIDATE')), force BOOLEAN DEFAULT FALSE);
1)表级统计信息
select table_name,num_rows,blocks,empty_blocks,avg_space from user_tables where table_name = 'TEST';
2)列级统计信息
select table_name,column_name,num_distinct,density from user_tab_columns where table_name = 'TEST';
3)列的直方图信息
select table_name,column_name,endpoint_number,endpoint_value
from user_tab_histograms
where table_name = 'TEST'
and column_name = 'OBJECT_ID';
4)分区统计信息
select partition_name,num_rows,blocks,empty_blocks,avg_space
from user_tab_partitions
where table_name = 'TEST';
5)分区上列的统计信息
select column_name,num_distinct,density,num_nulls
from user_part_col_statistics
where table_name = 'TEST'
and partition_name = 'P1';
6)分区上列的直方图信息
select column_name,bucket_number,endpoint_value
from user_part_histograms
where table_name = 'TEST'
and partition_name = 'P1'
and column_name = 'OBJECT_ID';