分类: Oracle
2008-05-24 19:05:59
来源: |
|
在Oracle9 i 之前的版本里,仅有的两种基于代价的优化器(cost-based optimizer,CBO)模式是ALL_ROWS和FIRST_ROWS优化。传统的FIRST_ROWS SQL优化的一个缺点是,这一算法没有指定数据行检索的。 但是Oracle9 i 引入了多种新的优化器命令: FIRST_ROWS_1 FIRST_ROWS_10 FIRST_ROWS_100 FIRST_ROWS_1000 FIRST_ROWS_ n 优化会查询优化器,让它选择一个能够把时间减到最小的查询执行计划,以产生查询结果的前 n 行。 你可以在数据库里的多个层次上设置这个新的CBO模式:系统范围内、会话这一层,或者在查询这一层。 alter system set optimizer_mode=first_rows_100; alter session set optimizer_mode = first_rows_100; select /*+ first_rows(100) */ from student; 根据Oracle的消息,有了FIRST_ROWS_ n 优化,Oracle查询会为结果集里的前 n 行给出最佳的可能响应时间。带有 n 行结果的快速响应会增强用户对很对应用程序的满意度,因为用户能够更快地获得数据集前面的结果。 ALL_ROWS优化更倾向于完整表格扫描,而FIRST_ROWS优化更倾向于索引的使用,但是Oracle用FIRST_ROWS_ n 优化了这一概念。 在传统的FIRST_ROWS优化里,Oracle CBO更倾向于索引检索,即使它的整体代价要比完整表格扫描更高。这在小表格的情况下尤其如此,因为这样进行完整表格扫描的代价不是太大。 想想下面的例子。 Set autotrace on explain alter session set optimizer_goal = choose; select * from emp where sal < 1200; PLAN ----------------------------------------------------- SELECT STATEMENT (OPTIMIZER=CHOOSE) (COST=62) (ROWS=99) TABLE ACCESS FULL EMP (COST=62) (ROWS=99) 现在,我们会用FIRST_ROWS优化运行同样的查询。 alter session set optimizer_goal = first_rows; select * from emp where sal < 1200; The explain plan is now transformed to: PLAN ----------------------------------------------------- SELECT STATEMENT (OPTIMIZER=FIRST_ROWS) (COST=102) TABLE ACCESS BY INDEX ROWID EMP (COST=102) (ROWS=99) INDEX RANGE SCAN SAL_IDX (COST=2) (ROWS=99) 尽管我们预计CBO会倾向于索引,但是我们很意外地看到FIRST_ROWS优化选择了一种比完整表格扫描代价更大的途径。这是就是关键点。在Oracle9 i 之前的版本里,FIRST_ROWS优化是内部规则和代价的混合体,而Oracle9 i 的FIRST_ROWS优化则完全是基于代价的。 在Oracle9 i 之前的版本里,我们会使用OPTIMIZER_INDEX_COST_ADJ参数来控制CBO的倾向,让其选择索引而不是完整表格扫描。 尽管Oracle宣称FIRST_ROWS_ n 优化会让查询更快,但是要记住的是,Oracle9 i CBO所做的一切只考虑了对前几行的访问,而牺牲了查询(的代价)。换句话说,FIRST_ROWS_ n 模式所做的一切是允许优化器作出更加智能的选择:在访问小表格的时候到底是使用索引还是完整表格扫描。由于大多数的Oracle9 i DBA都会在KEEP池里缓冲这些小表格,所以这个参数几乎没有什么用。 本文作者: Donald Burleson做数据库管理员已经有23年了,曾经写过14本关于数据库的书和超过100篇的文章。他是《Oracle内幕(Oracle Internals)》的主编,并经营着Burleson Oracle公司(Burleson Oracle Consulting)。 |