Statistic 对Oracle 是非常重要的。 它会收集数据库中对象的详细信息,并存储在相应的数据字典里。 根据这些统计信息, optimizer 可以对每个SQL 去选择最好的执行计划。
在9i 及之前的版本,在选择执行计划的时候会根据RBO(Rule-BasedOptimization)或者CBO来分析。 10g及以后版本只支持CBO(Cost-BasedOptimization)。
优化器收集的统计信息包括如下内容:
1)Table statistics
Number of rows(表行数)
Number of blocks(表的块数)
Average row length(行平均长度)
2)Column statistics
Number of distinct values (NDV) in column
Number of nulls in column
Data distribution (histogram)
3)Index statistics(索引统计信息)
Number of leaf blocks
Levels
Clustering factor
4)System statistics
I/O performance and utilization(I/O性能和使用率)
CPU performance and utilization
Oracle Statistic 的收集,可以使用analyze 命令,也可以使用DBMS_STATS 包来收集,Oracle 建议使用DBMS_STATS包来收集统计信息,因为DBMS_STATS包收集的更广,并且更准确。 analyze 在以后的版本中可能会被移除。
analyze 命令的语法如下:
SQL>analyze table tablename compute statistics;
SQL>analyze table tablename compute statistics for all indexes;
SQL>analyze table tablename delete statistics
关于DBMS_STATS包的使用,参考博客:http://blog.csdn.net/cymm_liu/article/details/22217191
Oracle 的Statistic 信息的收集分两种:自动收集和手工收集。 在这里,我们看一下自动收集的部分。 其他内容参考Oracle 的联机文档。
Oracle 的Automatic Statistics Gathering 是通过Scheduler 来实现收集和维护的。 Job 名称是GATHER_STATS_JOB, 该Job收集数据库所有对象的2种统计信息:
(1)Missing statistics(统计信息缺失)
(2)Stale statistics(统计信息陈旧)
该Job 是在数据库创建的时候自动创建,并由Scheduler来管理。Scheduler 在maintenance windows open时运行gather job。 默认情况下,job会在每天晚上10到早上6点和周末全天开启。该过程首先检测统计信息缺失和陈旧的对象。然后确定优先级,再开始进行统计信息。
Scheduler Job的 stop_on_window_close 属性控制GATHER_STATS_JOB 是否继续。该属性默认值为True. 如果该值设置为False,那么GATHER_STATS_JOB 会中断, 而没有收集完的对象将在下次启动时继续收集。
Gather_stats_job 调用dbms_stats.gather_database_stats_job_proc过程来收集statistics 的信息。 该过程收集对象statistics的条件如下:
(1)对象的统计信息之前没有收集过。
(2)当对象有超过10%的rows 被修改,此时对象的统计信息也称为stale statistics。
查看该Job 信息:
SQL> select job_name, program_name,enabled,stop_on_window_close from dba_scheduler_jobs where job_name = 'GATHER_STATS_JOB';
job_name program_name enabl stop_on_window_close
-------------------- -------------------- ----- --------------------
gather_stats_job gather_stats_prog true true
监控参数 STATISTICS_LEVEL:
为了决定是否对对象进行监控,Oracle 提供了一个参数STATISTICS_LEVEL。
通过设置初始化参数 STATISTIC_LEVEL 为 TYPICAL 或 ALL,就可以自动收集统计信息(默认值为 TYPICAL,因此可以随即启用自动收集统计信息的功能)。STATISTIC_LEVEL 参数的值可以激活GATHER_STATS_JOB。
在10g中表监控默认是激活的,如果STATISTICS_LEVEL设置为basic,不仅不能监控表,而且将禁掉如下一些10g的新功能:
(1)ASH(Active Session History)
(2)ASSM(Automatic Shared Memory Management)
(3)AWR(Automatic Workload Repository)
(4)ADDM(Automatic Database Diagnostic Monitor)
SQL> show parameter statistics_level
NAME TYPE VALUE
------------------------- ----------- ------------------------------
statistics_level string TYPICAL
当启动对象的监控后,从上次统计信息收集之后的的信息,如inserts,updates,deletes 等,这些改变的信息会记录到 user_tab_modifications视图。
当对象的数据发生改变之后, 经过几分钟的延时,这些信息写入到user_tab_modifications视图,然后dbms_stats.flush_database_monitoring_info过程就会发现这些信息,并讲这些信息保存在内存中。
当监控的对象被修改的部分超过10%时, gather_database_stats 或者 gather_schema_stats 过程就会去收集这些stale statistics.
停用该Job:
默认情况下,该Job是enable的。统计信息的收集是资源相当密集的工作,所以在某些情况下,就不希望它自动去收集,而考虑选择手动来收集。 这中情况下,我们可以设置statistics_level 为Basic,禁用对对象的监控,但是这样也会禁用AWR等信息的收集,这种情况下,我们就可以使用可以使用如下语句:
BEGIN
DBMS_SCHEDULER.DISABLE('GATHER_STATS_JOB');
END;
/
系统用户统计信息的收集:
如果想收集system schemas的统计信息,可以使用dbms_stats.gather_dictionary_stats过程。 该过程会收集所有system schemas,包括SYS和SYSTEM,和一些其他的chemas,如CTXSYS和 DRSYS.
三. 统计信息的存储位置
统计信息收集如下数据:
(1)表自身的分析: 包括表中的行数,数据块数,行长等信息。
(2)列的分析:包括列值的重复数,列上的空值,数据在列上的分布情况。
(3)索引的分析: 包括索引叶块的数量,索引的深度,索引的聚合因子等。
这些统计信息存放在数据字典里,如:
(1). DBA_TABLES
(2). DBA_OBJECT_TABLES
(3). DBA_TAB_STATISTICS
(4). DBA_TAB_COL_STATISTICS
(5). DBA_TAB_HISTOGRAMS
(6). DBA_INDEXES
(7). DBA_IND_STATISTICS
(8). DBA_CLUSTERS
(9). DBA_TAB_PARTITIONS
(10). DBA_TAB_SUBPARTITIONS
(11). DBA_IND_PARTITIONS
(12). DBA_IND_SUBPARTITIONS
(13). DBA_PART_COL_STATISTICS
(14). DBA_PART_HISTOGRAMS
(15). DBA_SUBPART_COL_STATISTICS
(16). DBA_SUBPART_HISTOGRAMS
3.1 表的统计信息:
包含表行数,使用的块数,空的块数,块的使用率,行迁移和链接的数量,pctfree,pctused的数据,行的平均大小:
SELECT NUM_ROWS, --表中的记录数
BLOCKS, --表中数据所占的数据块数
EMPTY_BLOCKS, --表中的空块数
AVG_SPACE, --数据块中平均的使用空间
CHAIN_CNT, --表中行连接和行迁移的数量
AVG_ROW_LEN --每条记录的平均长度
FROM USER_TABLES
3.2 索引列的统计信息
包含索引的深度(B-Tree的级别),索引叶级的块数量,集群因子(clustering_factor), 唯一值的个数。
SELECT BLEVEL, --索引的层数
LEAF_BLOCKS, --叶子结点的个数
DISTINCT_KEYS, --唯一值的个数
AVG_LEAF_BLOCKS_PER_KEY, --每个KEY的平均叶块个数
AVG_DATA_BLOCKS_PER_KEY, --每个KEY的平均数据块个数
CLUSTERING_FACTOR --群集因子
FROM USER_INDEXES
3.3 列的统计信息
包含 唯一的值个数,列最大小值,密度(选择率),数据分布(直方图信息),NUll值个数
SELECT NUM_DISTINCT, --唯一值的个数
LOW_VALUE, --列上的最小值
HIGH_VALUE, --列上的最大值
DENSITY, --选择率因子(密度)
NUM_NULLS, --空值的个数
NUM_BUCKETS, --直方图的BUCKET个数
HISTOGRAM --直方图的类型
FROM USER_TAB_COLUMNS
3.4 测试:表只有分析了之后,num_rows才会有值
SQL> create table dba as select * from dba_objects;
Table created.
SQL> select count(*) from dba;
COUNT(*)
----------
50123
SQL> select table_name,num_rows from dba_tables where table_name='DBA';
TABLE_NAME NUM_ROWS
------------------------------ ----------
DBA
--注意,这里为的num_rows 为空。 分析之后就有了
SQL> exec dbms_stats.gather_table_stats('SYS','DBA');
PL/SQL procedure successfully completed.
SQL> select table_name,num_rows from dba_tables where table_name='DBA';
TABLE_NAME NUM_ROWS
------------------------------ ----------
DBA 50123
所以,判断统计信息是否准确,只需要比较一下表记录的count 和 num_rows 值就知道了。 如果是一致的,就说明是最新的,如果不一致,可能就需要分析了。