在大多数情况下,执行一个SQL査询有多种方法。可以对全表进行扫描,或者使用一个索引来得到同样的结果。也可以通过以不同的顺序访问表和索引来检索同样的数据。Optimizer的工作就是寻找最理想的或最好的计划来执行DML语句,如SELECT.INSERT.UPDATE和DELETE。Oracle使用CBO(Cost-Based Optimizer,基于成本的优化程序)帮助确定执行査询的有效方法。
CBO使用表和索引的统计数据、SQL语句中表和列的顺序、可用的索引以及用戸提供的访问提示来选取访问数据的最有效的方法。按照CBO的结论,最有效的方法是成本最小的访问方法,这里,成本是根据花费在检索记录上的I/O和CPU时间来定义的。
访问必要的行意味着Oracle将文件系统中的数据库块读取到缓冲池中。由此产生的I/O成本是SQL语句执行过程中花费最多的部分,因为它涉及从磁盘读取。可以使用EXPLAIN PLAN这样的工具来检査这些访问路径。以下几节介绍为了确保优化程序的功能有效,你需要执行的任务。
1选择优化方式
在Oracle的旧版本中,可以在基于规则和基于成本的优化程序之间进行选择。在基于规则的方法中,Oracle使用启发式方法根据某些规则的帮助从几个备选的访问路径中进行选择。所有的访问路径都被分配了一个排序值,具有最低排序值的路径被选中。
具有较低排序值的操作通常要比具有较高排序值的操作执行得要快。例如,一个使用ROWID来搜索记录的查询其成本为1。这是我们所期望的,因为借助于ROWID(Oracle中一个类似指针的机制)的帮助来确定行是定位一行最快的方式。另一方面,使用全表扫描的査询其成木为19,是基于规则优化中最高的。CBO方法差不多总是要比老的、基于规则的方法执行得要快,这是因为除了别的原因之外,CBO方法还考虑了数据库对象的最新的统计数据。
2为优化程序提供统计数据
默认时,数据库本身会自动收集优化程序所需的统计数据。每天晚匕数据库会在Oracle Scheduler的维护窗期间调用统计数据收集作业。默认情况下,维护窗口在工作日的晚上10点到早上6点,以及周末的全天打开。默认情况下,在每个Oracle Database 11g中都有一个名为GATHER_STATS_JOB的作业在运行。如果愿意的话,你可以禁用GATHER_STATS_JOB作业。通过查询DBA_SCHEDULER_JOBS视图可以详细了解这个默认的GATHER_STATS_JOB作业。
GATHER_STATS_JOB作业为所有没有优化程序统计数据,或者只有陈旧的(过时的)统计数据的表收集统计数据。对于一个对象,如果自最近一次收集统计数据以来有超过10%的数据被更改,Oracle就认为该对象的统计数据过时了。默认情况下,Oracle监控全部数据库对象的所有DML更改,如插入、更新和删除等操作。还可以在DBA_TAB_MODIFICATIONS视图中查看有关这些更改的信息。根据这个默认的对象监控,Oracle决定是舂要为对象收集新的统计数据。
要想定期査验GATHER_STATS_JOB是否的确在收集统计数据,可以使用下面的程序:
SELECT last_analyzed, table_name, owner,
num_rows, sample_size FROM dba_tables ORDER by last_analyzed;
对于上面的输出,要注意以下几点。
Ø 该作业在数据库的维护窗口期间收集统计数据,默认情况下,维护窗口安排在工作日的晚上 10点到早上6点以及周末的全天。
Ø Scheduler在每天晚上运行GATHER_STATS_JOB来收集统计数据。
Ø 如果在某一天创建了表,那么该祐业在当天第一次为该表收集统计数据时使用表的所有行。
Ø 采样百分比的范围从小于1%-100%。
Ø 表的大小与釆样的百分比无关。
Ø 该作业并不是毎天都为所有的表收集统计数据。
Ø 如果表中的数据自创建后就没有变化,该作业就不会进行第二次收集。
Oracle根据其内部算法为每一个对象定义样本大小,不存在针对所有对象的一个标准的样本尺寸。检査了统计数据集合后,就可以将统计数据集合留给数据库去处理而关注其他地方。釆用这种方式,有可能持续多年运行一个庞大的产品数据库,而不需使用DBMS_STATS程序包来手工执行统计数据收集作业。
当然,如果在白天或者GATHER_STATS_JOB作业启动运行之后加载数据,可能会坐失良机,对象将不会有任何统计数据被收集。因此,在白美要时刻留意对象可能会发生的重大变化。可能需要在数据更改之后立即调度一个统计数据收集作业。
此外,利用DBMS_STATS程序包(由GATHER_STATS_JOB作业管理的自动统计数据收集进程也是使用同一个程序包在内部锂行统计数据收集)可以函优化程序提供必要的统计数据。必要的统计数据如下:
Ø 表的行数;
Ø 每个数据库块的行数;
Ø 行的平均长度;
Ø 表中数据库块的总数;
Ø 每个索引中的级别数;
Ø 每个索引中叶块的数目;
Ø 表中每一列的不同数据值的数目;
Ø 数据分布柱状图;
Ø 索引键的数目;
Ø 基数(具有相同取值的列数目);
Ø 每个列的最小值和最大值;
Ø 系统统计数据(包括系统的I/O特性)、CPU统计数据(包括CPU的速度)以及其他相关的统计数据。
CBO选取最可能査询计划的能力的关键是能正确估算査询计划中每个操作的成本。这些成本佔算基于表和索引的统计数据从执行每个操作所需要的I/O、CPU以及内存资源等知识推导出来。也可以基于前面所列举的操作系统的统计数据以及关于操作系统性能的额外信息进行估算。
数据库在数据字典中存储它收集的优化程序统计数据。DBA_TAB_STATISTICS表显示了数据库中所有表的优化程序统计数据。还可以通过査询DBA_TAB_Col_STATISTICS视图来査看列的统计数据,如下例所示:
SELECT column_name, num_distinct FROM
dba_tab_col_statistics WHERE table name='PERSONNEL';
正如所见,在PERSONNEL表中有超过2200万个PERSON_ID号。但是,只有7281个不同的姓(last name)和1729个不同的名(first name)。当然,GENDER列只看两个不同的值。优化程序在为一个涉及表中列的SQL语句决定最好的执行计划之前,会考虑有关表数据的这些类型的信息。
提示 优化程序统计数据包括对象(表和索引)统计数据以及系统统计数据。缺少正确的系统统计数据,优化程序就不能得出有效的成本估算,从而不能评估候选的执行计划,




