当前位置: 首页 > news >正文

Oracle的优化器

 一、目的:
  1、说一说Oracle的Optimizer及其相关的一些知识。
  2、回答一下为什么有时一个表的某个字段明明有索引,当观察一些SQL的执行计划时,发现确不走索引的问题。
  3、如果你对 FIRST_ROWS、 ALL_ROWS这两种模式有疑惑时也可以看一下这篇文章。

Oracle在执行一个SQL之前,首先要分析一下语句的执行计划,然后再按执行计划去执行。分析语句的执行计划的工作是由优化器(Optimizer)来完成的。不同的情况,一条SQL可能有多种执行计划,但在某一时点,一定只有一种执行计划是最优的,花费时间是最少的。

 

二、

 1、优化器的优化方式:

    Oracle的优化器共有两种的优化方式,即基于规则的优化方式(Rule-Based Optimization,简称为RBO)和基于代价的优化方式(Cost-Based Optimization,简称为CBO)。

  A、RBO方式:优化器在分析SQL语句时,所遵循的是Oracle内部预定的一些规则。

                         比如我们常见的,当一个where子句中的一列有索引时去走索引。

  B、CBO方式:依词义可知,它是看语句的代价(Cost)了,这里的代价主要指Cpu和内存。优化器在判断是否用这种方式时,主要参照的是表及索引的统计信息统计信息给出表的大小 、有多少行、每行的长度等信息。这些统计信息起初在库内是没有的,是你在做analyze后才出现的,很多的时侯过期统计信息会令优化器做出一个错误的执行计划,因些我们应及时更新这些信息。在Oracle8及以后的版本,Oracle列推荐用CBO的方式。

  不一定走索引就是优的,比如一个表只有两行数据,一次IO就可以完成全表的检索,而此时走索引时则需要两次IO,这时对这个表做全表扫描(full table scan)是最好的。

 

    2、优化器的优化模式(Optermizer Mode)
    优化模式包括Rule,Choose,First rows,All rows这四种方式,也就是我们以上所提及的。

     Rule:不用多说,即走基于规则的方式。

  Choose:这是我们应观注的,默认的情况下Oracle用的便是这种方式。指的是当一个表或索引有统计信息,则走CBO的方式,如果表或索引没统计信息,表又不是特别的小,而且相应的列有索引时,那么就走索引,走RBO的方式。

  First Rows:它与Choose方式是类似的,所不同的是当一个表有统计信息时,它将是以最快的方式返回查询的最先的几行,从总体上减少了响应时间。

  All Rows:也就是我们所说的Cost的方式,当一个表有统计信息时,它将以最快的方式返回表的所有的行,从总体上提高查询的吞吐量。没有统计信息则走基于规则的方式。


     3、如何设定选用哪种优化模式
     A、Instance级别:
  我们可以通过在init<SID>.ora文件中设定OPTIMIZER_MODE=RULE、OPTIMIZER_MODE=CHOOSE、OPTIMIZER_MODE=FIRST_ROWS、OPTIMIZER_MODE=ALL_ROWS去选用3所提的四种方式,如果你没设定OPTIMIZER_MODE参数则默认用的是Choose这种方式。

  B、Sessions级别:
  通过SQL> ALTER SESSION SET OPTIMIZER_MODE=<Mode>;来设定。


     C、语句级别:
  这些需要用到Hint

 

三、为什么有时一个表的某个字段明明有索引,当观察一些语的执行计划确不走索引呢?如何解决呢?

     A、不走索引大体有以下几个原因:
       1、你在Instance级别所用的是all_rows的方式
       2、你的表的统计信息(最可能的原因)
       3、你的表很小,上文提到过的,Oracle的优化器认为不值得走索引

  B、解决方法:
  1、可以修改init<SID>.ora中的OPTIMIZER_MODE这个参数,把它改为Rule或Choose,重起数据库。也可以使用4中

           所提的Hint.
  2 、删除统计信息:
       SQL>analyze table table_name delete statistics;
  3、表小不走索引是对的,不用调的。

四、相关:

     A、如何看一个表或索引是否是统计信息  B、如果我们先用CBO的方式,我们应及时去更新表和索引的统计信息,以免生形不切合实的执行计划:

相关文章:

  • oracle的case函数控制结构DECODE()函数
  • JQuery入门简介
  • Js字符串操作函数大全
  • js 运算符 || 妙用
  • javascript获得url中的参数
  • 获取浏览器的高度和宽度
  • js省市级联
  • C#调用外部程序
  • oracle学习笔记(一)分享
  • 日期时间脚本库方法列表
  • JS 打开新窗口的方法
  • js日期加减得到新的日期
  • Oracle 10g DBMS_SCHEDULER的中度解析
  • Oracle 10g schedule job的常用操作
  • 全面学习ORACLE Scheduler特性(1)创建jobs
  • C++回声服务器_9-epoll边缘触发模式版本服务器
  • CentOS 7 修改主机名
  • HTTP中的ETag在移动客户端的应用
  • iOS高仿微信项目、阴影圆角渐变色效果、卡片动画、波浪动画、路由框架等源码...
  • Java 23种设计模式 之单例模式 7种实现方式
  • MQ框架的比较
  • React-生命周期杂记
  • Redux 中间件分析
  • SpiderData 2019年2月16日 DApp数据排行榜
  • Three.js 再探 - 写一个跳一跳极简版游戏
  • 函数式编程与面向对象编程[4]:Scala的类型关联Type Alias
  • 检测对象或数组
  • 问:在指定的JSON数据中(最外层是数组)根据指定条件拿到匹配到的结果
  • 学习Vue.js的五个小例子
  • ​马来语翻译中文去哪比较好?
  • ​总结MySQL 的一些知识点:MySQL 选择数据库​
  • (52)只出现一次的数字III
  • (ibm)Java 语言的 XPath API
  • (JSP)EL——优化登录界面,获取对象,获取数据
  • (附源码)springboot助农电商系统 毕业设计 081919
  • (蓝桥杯每日一题)平方末尾及补充(常用的字符串函数功能)
  • (免费分享)基于springboot,vue疗养中心管理系统
  • (转)重识new
  • **python多态
  • .Net - 类的介绍
  • .net framework 4.0中如何 输出 form 的name属性。
  • .NET Remoting Basic(10)-创建不同宿主的客户端与服务器端
  • .NET Remoting学习笔记(三)信道
  • .NET/C# 获取一个正在运行的进程的命令行参数
  • @ModelAttribute 注解
  • @requestBody写与不写的情况
  • @WebService和@WebMethod注解的用法
  • [ C++ ] template 模板进阶 (特化,分离编译)
  • [ Linux 长征路第二篇] 基本指令head,tail,date,cal,find,grep,zip,tar,bc,unname
  • [ 渗透测试面试篇 ] 渗透测试面试题大集合(详解)(十)RCE (远程代码/命令执行漏洞)相关面试题
  • [ 手记 ] 关于tomcat开机启动设置问题
  • []FET-430SIM508 研究日志 11.3.31
  • [2016.7 Day.4] T1 游戏 [正解:二分图 偏解:奇葩贪心+模拟?(不知如何称呼不过居然比std还快)]
  • [8481302]博弈论 斯坦福game theory stanford week 1
  • [AI]文心一言爆火的同时,ChatGPT带来了这么多的开源项目你了解吗