一种通过ANALYZE命令,一种通过DBMS_STATS报中的GATHER_*方法获得,这两种是手动方式。从10G开始,这个工作是GATHER_STATS_JOB自动完成。
手动:
SQL>ANALYZE TABLE TABLE1 VALIDATE STRUCTURE CASCADE;
SQL>ANALYZE INDEX INDEX1 COMPUTE STATISTICS;
查看自动信息:
ORACLE 10G中:
SQL>EXEC DBMS_SCHEDULER.ENABLE('SYS.GATHER_STATS_JOB');--启动自动收集
SQL>EXEC DBMS_SCHEDULER.DISABLE('SYS.GATHER_STATS_JOB');--关闭自动收集
SQL>SELECT JOB_NAME, STATE, COMMENTS FROM DBA_SCHEDULER_JOBS WHERE JOB_NAME LIKE 'GATHER%';
如果有GATHER_STATS_JOB,那就是已经开启。
ORACLE 11G中:
ORACLE 11G中GATHER_STATS_JOB被BSLN_MAINTAIN_STATS_JOB替换了。
查询状态:
SQL> SELECT CLIENT_NAME, STATUS FROM DBA_AUTOTASK_CLIENT;
如果auto optimizer stats collection,auto space advisor,sql tuning advisor都ENABLED了就说明开启了。
TABLE MONITORING机制:
ORACLE 10G对对象收集优化:只针对那些发生了重大变化的,原有统计信息已经陈旧的对象才重新收集统计数据。
监控原理:
ORACLE会监控对象上发生的更改,包括INSERT、UPDATE、DELETE、TRUNCATE的数据量。如果改变的数据量超过记录总数的10%,则重新收集统计信息。监控收到参数STATISTICS_LEVEL控制。可以用如下语句查看:
SQL>SELECT STATISTICS_NAME, SYSTEM_STATUS, ACTIVATION_LEVEL, STATISTICS_VIEW_NAME FROM V$STATISTICS_LEVEL;
其中STATISTICS_LEVEL参数值被设置成TYPICAL或者ALL,就会启动表监控。
监控信息从USER_TAB_MODIFICATIONS视图中查看。
SQL> SELECT TABLE_NAME, PARTITION_NAME, INSERTS, UPDATES, DELETES, TRUNCATED, DROP_SEGMENTS, TABLE_OWNER FROM DBA_TAB_MODIFICATIONS WHERE TABLE_OWNER='SCOTT';
收集到的这些信息不是立即更新到系统字典中去,会拖延一段。
也可以手动使用DBMS_STATS.FLUSH_DATABASE_MONITORING_INFO方法直接手动同步。
除了可以跟踪DML,还会跟踪每个数据列在查询中的使用情况,从COL_USAGE$中查看。
SQL>SELECT * FROM COL_USAGE$;
其中LIKE_PREDS表示在LIKE条件中的使用次数。这些会被ADDM作为SQL Access Advisor的依据。
要想使用动态数据收集,需要把对象的统计信息设置成NULL。当ORACLE遇到一个统计信息是NULL的对象会动态收集其统计信息。就是通过抽取几个数据块作为样本来推算整个对象的统计信息。
初始化参数OPTIMIZER_DYNAMIC_SAMPLING,这个参数是采样提供数据块数量,缺省是2。
0:不适用动态统计信息收集。
1:使用32块进行统计信息收集。
2~9:分别是2、4、8、16、32、64、128、256倍的32块进行收集。
10:所有数据块。
还可以用HINT强行让优化器动态收集统计信息。
SQL>SELECT * from table1;
统计信息的变化历史可以从DBA_TAB_STATS_HISTORY视图中看到。它会记录过去31天来的统计信息被修改的历史。
SQL>SELECT * FROM DBA_TAB_STATS_HISTORY;
*注:ANALYZE命令产生的数据不会保存历史信息。
查看保留策略:
SQL>SELECT DBMS_STATS.GET_STATS_HISTORY_RETENTION FROM DUAL;
修改保留策略:
SQL>EXECUTE EBMS_STATS.ALTER_STATS_HISTORY_RETENTION(45);
统计的信息历史也受到STATISTICS_LEVEL的约束。如果是BASIC,则历史数据不会被自动清理。需要用DBMS_STATS.PURGE_STATS来手动清理。而且BASIC的时候也不会自动收集任何统计数据了。
查看实际可用最早日期:
SQL>SELECT DBMS_STATS.GET_STATS_HISTORY_AVAILABILITY FROM DUAL;
生产中有可能使用恢复历史统计信息,使用
SQL>EXEC DBMS_STATS.RESTORE_TABLE_STATS(OWNERNAME=>’ZXXX’,TABNAME=>’TABLE111’,AS_OF_TIMESTAMP=>’12-MAY-12 10.00.00.000000 AM+12:00’);
来恢复,具体里面的参数需要参考:
SQL>SELECT * FROM DBA_TAB_STATS_HISTORY WHERE TABLE_NAME=’TABLE111’;
来获得
CBO公式
Cost=IO+CPU÷1000+NetIO×1.5
IO代表物理IO操作量,
CPU代表逻辑IO操作量,
NetIO代表通过数据库连接的网络IO操作量。
Single_Block Read每次只会读取一个数据块,经过Buffer Cache,需要用OPTIMIZER_INDEX_CACHING来调整(默认为0)。Multi-Blocks Read会读取多个块,不经过Bufer Cache。
OPTIMZIER_INDEX_CACHING表示索引块被缓存在Buffer Cache中的比率,如果是0,就说明不缓存。如果是80,就表明80%的读取都是逻辑读,不需要物理读。
加入此因素,
COST=(总读取×(1-(OPTIMIZER_INDEX_CACHING÷100)))
×(OPTIMIZER_INDEX_COST_ADJ÷100)
OPTIMIZER_INDEX_COST_ADJ默认为100。
用下面这个SQL计算一下“连续读平均等待×100”与“分散读平均等待”的比值:
SQL>SELECT TRUNC(A.AVERAGE_WAIT*100/B.AVERAGE_WAIT) FROM
V$SYSTEM_EVENT A, V$SYSTEM_EVENT B
WHERE A.EVENT='db file sequential read' and
b.event='db file scattered read';
得到的结果,可以设置为OPTIMIZER_INDEX_COST_ADJ参数。
ORACLE把IO收集信息放在SYS.AUX_SATS$中,包含两类信息,SYSSTATS_INFO和SYSSTATS_MAIN。
SYSSTATS_INFO描述收集活动自身。
SYSSTATS_MAIN表述真正收集的数据。
操作系统统计数据分成两类:无负载模式NOWORKLOAD,和负载模式WORKLOAD。
无负载模式在数据库启动时就会收集。
负载模式需要手动收集。
两种界定根据自身业务需要,例如凌晨是无负载模式,工作时间是负载模式。