打算对10g的优化器做一些基础介绍,这个是第一帖
[@more@]SQL的逻辑与物理
让我们以一个语句来开始我们的话题, 这个语句并不是以我们熟悉的SQL如”select c1, c2 from …”的方式给出, 而是以我们更加熟悉的陈述方式给出: “今天我需要去商店买冷饮,给汽车加油, 还有寄包裹,”. 假如我们有一个机器人(Robot Oracle)负责决定如何完成这些任务, 默认的, 它可能会按照我们输入的指令的顺序来完成任务, 这样做任务当然可以完成, 但很可能不是完成任务的最好方式.
如果先买冷饮, 冷饮会不会在完成其他任务的过程中化掉?
如果在去加油站的路上油就用光了怎么办?
当我们到邮局的时候邮局会不会下班?
是的, Robot Oracle需要做的是给我们提供完成这些任务的最佳方案, 然而至少目前它无法很好的完成这件事情, 为什么? 因为信息不足!
我们需要提供足够的信息, 比如商店, 邮局, 加油站的位置; 商店, 加油站, 邮局的营业时间; 冷饮可以保留多久不会化掉, 我们现在车里有多少油? 提供的信息越完善, 越准确, 我们越有可能得到最佳方案, 否则, no信息, no优化!
同样, SQL语句的处理也存在它自身的逻辑. 这个逻辑的处理过程可以保证得到正确的结果, 但绝不考虑性能. 比如向下面这个简单的语句:
(7) Select d.dept_name, count(e.emp_id) as numbers
(1) From employees as e
(3) Left outer join deptment as d
(2) On e.dep_id=d.dep_id
(4) Where e.city = ‘ShangHai’
(5) Group by d.dept_name
(6) Having count(e.emp_id) < 30
(8) Order by numbers;
在上面这个语句里, 我用数字来表示SQL逻辑处理的步骤顺序, 每一个步骤都是一个独立的操作, 会产生一个中间的数据集合, 或者说是虚拟表(简称VT), 作为下一个操作的输入(当然, 除了最后一步是把结果发给语句的调用者). 我们可以认为这些独立的操作都使用标准的方法, 比如方法open来开始接收数据输入, 方法operate_row来生成新数据, 方法close来告诉下一个操作接收数据.
简单介绍一下每一个步骤:
- From, 对From子句中的前两个表执行笛卡尔积(Cartesian product), 生成虚拟表VT1.
- ON, 对VT1进行筛选, 只保留符合join条件的行, 生成VT2
- Outer join, 处理Left outer join, 在这里employees表被作为保留表, 因此所有在步骤2里被排除的employees表的数据都被添加回来, 对应的deptment的列设置null. 生成VT3.
- Where, 对VT3进行where筛选, 只有where里条件为true的行才被插入VT4.
- Group by, 按照group by后面的列明对VT4进行分组, 生成VT5.
- Having, 对VT5进行Having筛选, 条件为true的插入VT6
- Select, 处理Select列表, 按照group by的分组方式计算每组的count, 生成VT7
- Order by, 对VT7进行排序.
SQL的逻辑处理过程是不考虑性能的, 而实际上我们知道, SQL的实际的, 或者说物理的处理是完全不一样的, 逻辑处理和物理处理完全是两个不同个概念, 在物理的层面上我们是可以走很多捷径的, 这正是Oracle优化器存在的意义
Oracle的优化器的作用, 就是为SQL生成最优化的执行计划, 这些计划生成的前提是确保可以得到正确的结果, 无法保证得回正确结果的执行计划是不会被考虑的(绝不能我们需要冷饮却给我们带回热茶), 而我们也需要提供足够的信息来保证优化器生成的执行计划是足够优化的, 在Oracle里, 这些信息叫做statistics.
我们知道SQL是"陈述式"的语言, 提交SQL的时候我们只关心我们需要什么样的数据, 而至于SQL的具体如何执行, 应该以什么样的顺序访问表, 以什么方式访问哪一个索引, 使用什么联结(join)算法, 这些都是优化器应该考虑的事情.
我们在小学就学习过, 可以通过多种途径获取同一个集合的结果,
例如: A È ( B Ç C ) = ( A È B ) Ç ( A È C )
同样, 由于SQL语言是基于集合操作的语言, 所以对于同一个SQL语句的结果集,我们是可以通过多种途径来执行SQL的(比如调整表之间的联结顺序), 这是优化器的工作之一, 甚至进一步, 优化器可以寻找到一些物理上的捷径来执行SQL (比如选择使用索引).
换句话说,Oracle优化器的作用就是把基于集合的SQL语言转化成为一系列中间步骤,这些中间步骤会通过过程化语言(确切的说,C语言)来完成SQL所要做的事情。这里的一系列的中间步骤就是我们通常所说的执行计划。
Oracle提供过两种优化器,一种是rule based optimizer(RBO),一种是cost based optimizer(CBO),RBO是通过一系列的写死在代码中的规则来生成SQL的执行计划,CBO则是通过搜集相关的统计信息(statistics)来根据具体情况来生成SQL的执行计划。由于CBO是根据具体环境得出解决方案,因此相对与RBO更加灵活,得到的执行计划往往也更优秀,而且有很多特性是只被CBO支持的,他们包括:
- Parallelism
- Reverse index scans
- Partition view elimination
- Star joins
- Hash joins
- Fast full index scans
- Function-based indexes
- Materialized views
- Temporary tables
- Domains
RBO是过气的产品了,在Oracle10g里已经不再支持RBO了。
。
来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/28434/viewspace-1002632/,如需转载,请注明出处,否则将追究法律责任。
转载于:http://blog.itpub.net/28434/viewspace-1002632/