日期:2014-05-16  浏览次数:20456 次

为何要分析数据字典

客户现场总是有人抱怨Oracle性能差,而发现大多数问题都是由于Oracle数据字典中的元数据过期,导致Oracle查询时候无法使用索引,继而导致的性能低下。

在此需要先解释一下“Oracle优化器”。ORACLE有两种优化器:基于规则的优化器(RBO,Rule Based Optimizer),和基于成本的优化器(CBO, Cost Based Optimizer)。

ORACLE公司已经不再发展“基于规则的优化器”技术,换句话说,这种优化技术被淘汰了。它的基本原理是只要你按照一套严格的使用规则去写SQL语句,无论数据表中的内容怎样,也不会影响到你的“执行计划”,也就是说对数据不“敏感”,

“基于成本的优化器”才是当前的主流,当前Oracle的许多新技术也都是基于CBO的,如星型连接排列查询,哈希连接查询,和并行查询等。CBO计算各种可能“执行计划”的“成本”,即cost,从中选用cost最低的方案,作为实际运行方案。各“执行计划”的cost的计算根据,依赖于数据表中数据的统计分布,ORACLE数据库本身对该统计分布并不清楚,须要分析表和相关的索引,才能搜集到CBO所需的数据。

????一般而言,基于成本的优化器所选择的“执行计划”都会比基于规整的优化器的“执行计划”好,而且相对而言,基于成本的优化器对程序员的要求也简单些,节省了程序员为了从多个可能的“执行计划”中选择一个最优的方案而花费的调试时间,

????举个最简单的例子说明基于成本的优化器是如何影响最后的运行方案,比如有一个表A,现在写了select * from a where a.condition = xxxx;。Oracle现在烦嘀咕了,到底是用a.condition索引来查询,还是进行全表查询呢?如果这个表只有50条记录,当然直接用全表扫描效果更好;但是如果这个表有50万条记录当然要用索引。而Oracle本身并不清楚这个表到底有50条记录还是50万条记录(Oracle不会笨到每次执行前都去select count(*)? from a一下,这样效率太低了)。那最好有一个字典表来保留这些数据,当这个表每天insert操作很多就每天来更新字典表中的这些数据(表的大小--50条或者50万条);又如果这个表是针对数据仓库的,虽然表很大但是总量相对稳定,则每周或者每月来更新一次。(注意:本例子是最最最简单的情况,仅仅为了说明基本道理,实际情况Oracle会做很多工作,同时也会带来的性能改善和性能恶梦)



??? 下面再来说说如何诊断和解决这些问题,我这里仅仅给出最简单的诊断以及维护方案,既便于大家理解,也便于学习,而且这最简单的方法也确实可以解决大多数问题。

??? 当你已经确定建过索引,但是性能又出奇的差,你可以根据如下步骤来进行:

??? 1、判断是否字典表失效。

??????? select table_name,num_rows,last_analyzed from user_tables;

??? 如果当你看到又大量的num_rows没有数值,或者last_analyzed是很久以前的日子了,那么恭喜你,你已经找到问题的根源了,也无需再去查什么user_indexes表了,user_tables中的数据有问题,user_indexes肯定也是不正确的。

???

??? 2、维护数据字典。

????????analyze table xxxx compute statistics for all indexes;

??????? 或者:ANALYZE TABLE xxxx ESTIMATE STATISTICS SAMPLE 5 PERCENT;

??????? 可以把需要要分析的表一个一个的这么执行。

??????? oracle 9i以后都提供了系统维护包,可以一次执行一个schema的所有内容:EXEC DBMS_UTILITY.analyze_schema('XXXXSchema','ESTIMATE', estimate_percent => 5); estimate_percent是指分析时候的采样百分比,百分比越小分析的越快,但是精度稍微差点。



??? 3、执行一个SQL验证一下,一般问题也就解决了。



??? 上述的初步提及了基于成本的优化器的原理,以及Oracle是如何使用基于成本的优化器来生成其执行计划,并给出了最简单的维护手段,虽然简单,但是解决80%的常见问题。