oracle 10gR2 sql查询性能相关摘要

http://lzfhope.blog.163.com/blog/static/6363992200811296039755/?suggestedreading&wumii

 环境:ORACLE 10G
     这里着重要研究的是一些很常见的,但是有和性能有密切关系的写法。
     不讨论函数,索引,分区等等因素,主要是SQL引擎的执行计划,具体一点就是:连接,条件,视图(主要是内建视图)。
     限于本人对于SQL引擎的了解,这里逐一列举几个例子。
     一) 关于 where 条件后面的常量表达式,例如1=1
     事实上,这是为了方便编写动态sql而写的 ,有的人也到处都这么写,仅仅是因为一个习惯,但是不建议到处写。会不会影响性能呢? 结论是 基本上不会影响,为什么呢? 因为10g的SQL引擎在解析前已经把这个条件过滤掉了。
     推而广之,其实大部分最终可以变为常量的表达式,都会在解析的时候被计算为常量:一个字符串,一个数值,或者一个布尔变量。 
     如果存在这样的一个where 子句
         (1=1) and  xxx ,那么会解析为 xxx.
           (1>1)   and xxx     ,会解析为 false ,并且不执行查询
           (1=1)  or  xxx ,        解析为  xxx 
           (1>1)  or xxx        , 解析为 false ,并且不执行查询.
            cola>100/2         ,会解析为cola>50 
     所以,针对很久以前的sql解析的法则,现在已经不通了,大家写的时候也不要再去关注,当然cola>100/2还是写成cola>50 比较好,无论如何解析也是需要花费时间的。
     二)关联条件还是过滤条件的选择
     例如有两个表格,  
      员工表  a(id,dept,name)  ,  工资表b(id,mon,salary)
      查询特定月份每个部门累计工资,可以如下编写
      select a.dept,sum(b.salary) from
                 a join b on b.id=a.id  where b.mon = 200812 group by  a.dept
      也可以如此写
      select a.dept,sum(b.salary) from
                 a join b on b.id=a.id  and b.mon = 200812 group by  a.dept
      它们的分析计划是一样的,这是因为对于oracle 10g的SQL引擎而言,可以单单作用于一个表格上的条件,是需要先在表格内部处理,然后才会处理其它步骤。
       上例子是针对join(简单连接或者内连接),我的结论是:选择关联条件还是过滤条件对于内连接是没有差别的。
  如果是外部连接(outer)或者其它连接(anti 差,semi 交)则另当别论!
  如果结合上索引情况会更复杂,不过这里暂时不说索引的事情。
  无论如何,谨记尽量使用explain 分析sql语句是很重要的。并且在很多时候注意使用hint,因为即使是执行计划,也不是很可信的。      
     三) 表格顺序
  曾经,有人说,表格的顺序很重要。
  我说,没错,但那仅仅是曾经而已,对于10g而言,这些发生了变化。
     现在要下两个结论:
  1)如果都是inner join(无论是否有明确指定顺序的),那么oracle会自动地在结果集合比较小的那个表格开始执行 (不考虑索引,条件等)。下一个表格是什么则取决于第一表关联的对象,然后才是其它。
        例如  select a.*,b*,c* from a,b,c where a.id=b.id and c.id=a.id
       select  a.*,b*,c* from a join b on b.id=a.id join c on c.id=a.id
     2)一切以执行计划为准,但可以通过调整语句来改变执行计划。

 http://lzfhope.blog.163.com/blog/static/636399220082214551786/

 3.2 DISTINCT|UNIQUE
        我们可以希望只返回重复行中的一行,那么可以在语句中设置distinct或者unique.
        限制:1)当设置了distinct或者unique的时候,select语句列表中的列所包含的所有字节总数是受到限制的,必须等于数据块的大小减去一些负载信息(不是很明白)?. the total number of bytes in all select list
expressions is limited to the size of a data block minus some overhead 。2)如果列包含了lob,那么不能使用distinct或者unique。

 3.9)样品(抽样)语句(sample clause)
         使用抽样语句,可以只随机选择一部分数据,而不是所有的数据.包括行随机抽样(sample),以及块随机抽样(block).   
         语法 select * from tab sample(N) seed(S)
    例子: 
                   SQL> select * from test_flashback sample(50);          
                   SID FULLNAME
            ---------- ----------------------------------------
                   101 天南地北          
            SQL> select * from test_flashback sample(50);          
                   SID FULLNAME
            ---------- ----------------------------------------
                   101 天南地北
                   101 五湖四海          
            SQL> select * from test_flashback sample(50);          
                   SID FULLNAME
            ---------- ----------------------------------------
                   101 五湖四海
                   101 三山五岳
   其中函数sample(N),N是在区间[0.000001,100)之内的数,可以称呼为命中率.表格或者视图的数据越多则这个函数的效果越好。这个函数在某些时候还是非常有用的.SEED(S)中的S介于[0,4294967295]之间,该函数主要是用于保证返回的结果集合和前次的同样S取值的一样。
  要保证采取块抽取,则可以用 /*+full*/ 或者/*+INDEX_FFS*/的强制提示来执行语句。
  限制:1)只有一个视图是包含主键的时候,才可以用抽样语句;2)在DML语句的子查询中不能使用抽样语句.  

原文地址:https://www.cnblogs.com/rattersnake/p/2993449.html