Query Optimizer
Query Optimizer
Oracle 的优化器有两种优化方式:
基于规则的优化方式:Rule-Based Optimization (RBO)
基于成本或者统计信息的优化方式:Cost-Based Optimization (CBO)

RBO(Rule-Based Optimization)
RBO: Rule-Based Optimization 也即 “基于规则的优化器”,该优化器按照硬编码在数据库中的一系列规则来决定 SQL 的执行计划。
以 Oracle 数据库为例,RBO 根据 Oracle 指定的优先顺序规则,对指定的表进行执行计划的选择。比如在规则中:索引的优先级大于全表扫描。
通过 Oracle 的这个例子我们可以感受到,在 RBO 中,有着一套严格的使用规则,只要你按照规则去写 SQL 语句,无论数据表中的内容怎样,也不会影响到你的 “执行计划”,也就是说 RBO 对数据不 “敏感”。这就要求开发人员非常了解 RBO 的各项细则,不熟悉规则的开发人员写出来的 SQL 性能可能非常差。
但在实际的过程中,数据的量级会严重影响同样 SQL 的性能,这也是 RBO 的缺陷所在。毕竟规则是死的,数据是变化的,所以 RBO 生成的执行计划往往是不可靠的,不是最优的。
CBO(Cost-Based Optimization)
CBO: Cost-Based Optimization 也即 “基于代价的优化器”,该优化器通过根据优化规则对关系表达式进行转换,生成多个执行计划,然后 CBO 会通过根据统计信息 (Statistics) 和代价模型 (Cost Model) 计算各种可能 “执行计划” 的 “代价”,即 COST,从中选用 COST 最低的执行方案,作为实际运行方案。
CBO 依赖数据库对象的统计信息,统计信息的准确与否会影响 CBO 做出最优的选择。统计信息包括 SQL 执行路径的 I/O、网络资源、CPU 的使用情况。
从 Oracle 10g 开始,Oracle 已经彻底放弃 RBO,转而使用 CBO。
配置优化器
查看数据库当前优化模式:
SQL> show parameter optimizer_mode |
在 Oracle 9i 及以上,优化器模式可以选择 first_rows_n, all_rows, choose, rule 等模式。其中 first_rows_n 又有 first_rows_1000, first_rows_100, first_rows_10, first_rows_1。
- Rule: 基于规则的方式。
- Choose:指的是当一个表或或索引有统计信息,则走 CBO 的方式,如果表或索引没统计信息,表又不是特别的小,而且相应的列有索引时,那么就走索引,走 RBO 的方式。
- First Rows:它与 Choose 方式是类似的,所不同的是当一个表有统计信息时,它将是以最快的方式返回查询的最先的几行,从总体上减少了响应时间。
- All Rows: 10g 中的默认值,也就是我们所说的 Cost 的方式,当一个表有统计信息时,它将以最快的方式返回表的所有的行,从总体上提高查询的吞吐
Oracle 10g 及以上,不再支持 RBO,Oracle 10g 官方文档关于 optimizer_mode 参数的只有 first_rows 和 all_rows,但是为了过渡或向下兼容依然可以设置 optimizer_mode 为 rule 或 choose。
Oracle 10g 及以上,优化器可以从系统级别、会话级别、语句级别三种方式修改优化器模式:
系统级别
SQL> alter system set optimizer_mode=rule scope=both; |
会话级别
会话级别修改优化器模式,只对当前会话有效,其它会话依然使用系统优化器模式。
SQL> alter session set optimizer_mode=first_rows_100; |
语句级别
语句级别通过使用提示 hint 来实现。
SQL> select /*+ rule */ * from dba_objects where rownum <= 10; |