`
lwyingdao
  • 浏览: 19404 次
  • 性别: Icon_minigender_1
  • 来自: 武汉
文章分类
社区版块
存档分类

oracle中的Where子句的条件书写顺序对性能影响

阅读更多
结论:oracle中where子句的顺序对性能无影响,但表的顺序对性能有影响,表按照从大到小以从右至左的顺序排列性能最好,影响sql的执行顺序是从右至左的。

经常有人问到oracle中的Where子句的条件书写顺序是否对SQL性能有影响,我的直觉是没有影响,因为如果这个顺序有影响,Oracle应该早就能够做到自动优化,但一直没有关于这方面的确凿证据。在网上查到的文章,一般认为在RBO优化器模式下无影响(10G开始,缺省为RBO优化器模式),而在CBO优化器模式下有影响,主要有两种观点:

    a.能使结果最少的条件放在最右边,SQL执行是按从右到左进行结果集的筛选的;

    b.有人试验表明,能使结果最少的条件放在最左边,SQL性能更高。

    查过oracle8到11G的在线文档,关于SQL优化相关章节,没有任何文档说过where子句中的条件对SQL性能有影响,到底哪种观点是对的,没有一种确切的结论,只好自己来做实验证明。结果表明,SQL条件的执行是从右到左的,但条件的顺序对SQL性能没有影响。

    实验一:证明了SQL的语法分析是从右到左的

    下面的试验在9i和10G都可以得到相同的结果: 第1条语句执行不会出错,第2条语句会提示除数不能为零。

    1.Select 'ok' From Dual Where 1 / 0 = 1 And 1 = 2;

    2.Select 'ok' From Dual Where 1 = 2 And 1 / 0 = 1;

    证明了SQL的语法分析是从右到左的。

    实验二:证明了SQL条件的执行是从右到左的

    drop table temp;

    create table temp( t1 varchar2(10),t2 varchar2(10));

    insert into temp values('zm','abcde');

    insert into temp values('sz','1');

    insert into temp values('sz','2');

    commit;

    1. select * from temp where to_number(t2)>1 and t1='sz';

    2. select * from temp where t1='sz' and to_number(t2)>1;

    在9i上执行, 第1条语句执行不会出错,第2条语句会提示“无效的数字”

    在10G上执行,两条语句都不会出错。

    说明:9i上,SQL条件的执行确实是从右到左的,但是10G做了什么调整呢?

    实验三:证明了在10g上SQL条件的执行是从右到左的

    Create Or Replace Function F1(v_In Varchar2) Return Varchar2 Is

    Begin

    Dbms_Output.Put_Line('exec F1');

    Return v_In;

    End F1;

    /

    Create Or Replace Function F2(v_In Varchar2) Return Varchar2 Is

    Begin

    Dbms_Output.Put_Line('exec F2');

    Return v_In;

    End F2;

    /

    SQL> set serverout on;

    SQL> select 1 from dual where f1('1')='1' and f2('1')='1';

    1

  ----------

    1

    exec F2

    exec F1

    SQL> select 1 from dual where f2('1')='1' and f1('1')='1';

    1

  ----------

    1

    exec F1

    exec F2

    结果表明,SQL条件的执行顺序是从右到左的。

那么,根据这个结果来分析,把能使结果最少的条件放在最右边,是否会减少其它条件执行时所用的记录数量,从而提高性能呢?

  例如:下面的SQL条件,是否应该调整SQL条件的顺序呢?

  Where A.结帐id Is Not Null

  And A.记录状态<>0

  And A.记帐费用=1

  And (Nvl(A.实收金额, 0)<>Nvl(A.结帐金额, 0) Or Nvl(A.结帐金额, 0)=0)

  And A.病人ID=[1] And Instr([2],','||Nvl(A.主页ID,0)||',')>0

  And A.登记时间Between [3] And [4]

  And A.门诊标志<>1

  实际上,从这条SQL语句的执行计划来分析,Oracle首先会找出条件中使用索引或表间连接的条件,以此来过滤数据集,然后对这些结果数据块所涉及的记录逐一检查是否符合所有条件,所以条件顺序对性能几乎没有影响。

  如果没有索引和表间连接的情况,条件的顺序是否对性能有影响呢?再来看一个实验。

  实验四:证明了条件的顺序对性能没有影响。

  SQL> select count(*) from诊疗项目目录where操作类型='1';

  COUNT(*)

  ----------

  3251

  SQL> select count(*) from诊疗项目目录where类别='Z';

  COUNT(*)

170

  SQL> select count(*) from诊疗项目目录where类别='Z' and操作类型='1';

  COUNT(*)

  ----------

  1

  Declare

  V1 Varchar2(20);

  Begin

  For I In 1 .. 1000 Loop

  --Select名称Into V1 From诊疗项目目录Where类别= 'Z' And操作类型= '1';

  select名称Into V1 from诊疗项目目录where操作类型='1' and类别='Z';

  End Loop;

  End;

  /

  上面的SQL按两种方式分别执行了1000次查询,结果如下:

  操作类型= '1'在最右|类别='Z'在最右

  0.093                          |    1.014

  1.06                            |    0.999

  0.998                          |    1.014

  按理说,从右到左的顺序执行,“类别='Z'”在最右边时,先过滤得到170条记录,再从中找符合“操作类型 = '1'”的,比较而言,“操作类型 = '1'”在最右边时,先过滤得到3251条记录,再从中找符合“类别='Z'”,效率应该要低些,而实际结果却是两者所共的时间差不多。

  其实,从Oracle的数据访问原理来分析,两种顺序的写法,执行计划都是一样的,都是全表扫描,都要依次访问该表的所有数据块,对每一个数据块中的行,逐一检查是否同时符合两个条件。所以,就不存在先过滤出多少条数据的问题。

  综上所述,Where子句中条件的顺序对性能没有影响(不管是CBO还是RBO优化器模式),注意,额外说一下,这里只是说条件的顺序,不包含表的顺序。在RBO优化器模式下,表应按结果记录数从大到小的顺序从左到右来排列,因为表间连接时,最右边的表会被放到嵌套循环的最外层。最外层的循环次数越少,效率越高。


来源:考试大-Oracle认证考试
分享到:
评论

相关推荐

    08.Oracle的where子句1

    一、生成测试数据用以下SQL创建超女基本信息表(T_GIRL),插入一些测试数据 二、where子句的语法select 字段名1,字段名2,字段名n from

    oracle中where 子句和having子句中的区别介绍

    主要介绍了在oracle中where 子句和having子句中的区别,本文通过sql语句给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友可以参考下

    Oracle Sql 性能优化

    ORACLE采用自下而上的顺序解析WHERE子句,根据这个原理,表之间的连接必须写在其他WHERE条件之前, 那些可以过滤掉最大数量记录的条件必须写在WHERE子句的末尾. 3、SELECT中避免使用 ‘ * ‘: ORACLE在解析的过程中, ...

    oracle语句优化方法.txt

    1) 选择最有效率的表名顺序(只在基于规则的优化器中有效)...ORACLE采用自下而上的顺序解析WHERE子句,根据这个原理,表之间的连接必须写在其他WHERE条件之前, 那些可以过滤掉最大数量记录的条件必须写在WHERE子句的末尾.

    MySQL数据库:where子句.pptx

    数据查询;;WHERE子句;WHERE子句;比较运算符用于比较(除TEXT和BLOB类型外) 两个表达式值,MySQL支持的比较运算符有:=(等于)、&lt;(小于)、(小于等于)、&gt;(大于)、&gt;=(大于等于)、...where子句中的比较运算 ;谢谢

    易语言学习进阶WHERE子句

    易语言学习进阶WHERE子句源码,学习进阶WHERE子句

    ORACLE_SQL性能优化

    ORACLE采用自下而上的顺序解析WHERE子句,根据这个原理,表之间的连接必须写在其他WHERE条件之前, 那些可以过滤掉最大数量记录的条件必须写在WHERE子句的末尾. (3) SELECT子句中避免使用 ‘ * ‘: ORACLE在解析的...

    T-SQL中where子句与having子句的对比分析.pdf

    T-SQL中where子句与having子句的对比分析.pdf

    SQL中where子句与having子句的区别小结

    主要给大家介绍了关于SQL中where子句与having子句的区别的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

    熟练编写存储过程,抓住where子句

    数据库的学习是一项艰巨的任务,其中的存储过程尤其重要且难以学通……希望这些资源对你有所帮助!

    精确分析MySQL数据库中优化WHERE子句

    本文精确分析了MySQL数据库中优化WHERE子句。

    SEIECT—SQL语句中Where子句功能解析与应用.pdf

    SEIECT—SQL语句中Where子句功能解析与应用.pdf

    oracle SQL性能优化

    ORACLE采用自下而上的顺序解析WHERE子句,根据这个原理,表之间的连接必须写在其他WHERE条件之前, 那些可以过滤掉最大数量记录的条件必须写在WHERE子句的末尾. (3) SELECT子句中避免使用 ‘ * ‘: ORACLE在解析的...

    详析SQL语言的WHERE子句与HAVING子句.pdf

    详析SQL语言的WHERE子句与HAVING子句.pdf

    where 子句的执行顺序

    貌似在2005之前的版本中,where子句的顺序是从前往后的。但是又貌似在2005的版本中进行了优化,所有的顺序都被统一成了以过滤能力进行排序的语句。

    ORACLE SQL性能优化

    比如当一个where子句中的一列有索引时去走索引。 COST (基于成本) 你必须经常运行analyze 命令,以增加数据库中的对象统计信息(object statistics)的准确性. CHOOSE (选择性) 如果table已经被analyze过, 优化器...

    MySQL使用WHERE子句设置查询条件

    WHERE子句设置查询条件,过滤掉不需要的数据行。  例如下面语句查询年龄大于10的数据: SELECT * FROM student WHERE age&gt;10  WHERE子句可包括各种条件运算符: 运算符 表示形式 比较运算符(大小比较) &gt;、...

    易语言学习进阶WHERE子句源码

    易语言学习进阶WHERE子句源码。@资源源码站。

    T396240109.zip VB.net中,如何动态构建Linq的Where子句

    T396240109.zip VB.net中,如何动态构建Linq的Where子句 https://bbs.csdn.net/topics/396240109

Global site tag (gtag.js) - Google Analytics