• oracle表查询优化


    ORACLE有个高速缓冲的概念,这个高速缓冲就是存放执行过的SQL语句,那oracle在执行sql语句的时候要做很多工作,例如解析sql语句,估算索引利用率,绑定变量,读取数据块等等这些操作。假设高速缓冲里已经存储了执行过的sql语句,那就直接匹配执行了,少了步骤,自然就快了,但是经过测试会发现高速缓冲只对简单的表起作用,多表的情况完全没有效果,例如在查询单表的时候那叫一个快,但是假设连接多个表,就龟速了。
    最重要一点,ORACLE的高速缓冲是全字符匹配的,什么意思呢,看下面三个select

    --No.1
    select * from tableA;
    --No.2
    select * From tableA;
    --No.3
    select * from tableA;

    这三个语句乍一看是一样的,但是高速缓存是不认的,是全字符匹配的,索引在高速缓存里会存储三条不同的语句,说到这里,又引出一个习惯,就是要保持良好的编程习惯,这个很重要

                

    ORACLE多表优化我积累了一些,都是常用的,介绍下

    一、FROM子句后面的表顺序有讲究

    先说为啥,ORACLE在解析sql语句的时候对FROM子句后面的表名是从右往左解析的,是先扫描最右边的表,然后在扫描左边的表,然后用左边的表匹配数据,匹配成功后就合并。 所以,在对多表查询中,一定要把小表写在最右边,为什么自己想想就明白了。例如下面的两个语句:

    --No.1  tableA:100w条记录  tableB:1w条记录 执行速度十秒
    select count(*) from tableA, tableB;

    --No.2 执行速度百秒甚至更高
    select count(*) from tableB, tableA;

    这个估计很多人都知道,但是要确认非常有用。

    还有一种是三张表的查询,例如

    select count(1) from tableA a,tableB b ,tableC c where a.id=b.id and a.id=c.id;

    上面中tableA 为交叉表,根据oracle对From子句从右向左的扫描方式,应该把交叉表放在最末尾,然后才是最小表,所以上面的应该这样写

    --tableA a 交叉表 
    --tabelB b 100w
    --tableC c 1w
    select count(1) from tableB b ,tableC c ,tableA a where a.id=b.id and a.id=c.id;

    这种写法对大数据量会非常有用,大家谨记,也是很常用的。

                

    二、Where子句后面的条件过滤有讲究,ORACLE对where子句后面的条件过滤是自下向上,从右向左扫描的,所以和From子句一样一样的,把过滤条件排个序,按过滤数据的大小,自然就是最少数据的那个条件写在最下面,最右边,依次类推,例如

    --No.1 不可取 性能低下
    select * from tableA a where
    a.id>500
    and a.lx = '2b'
    and a.id < (select count(1) from tableA where id=a.id)

    --No.2 性能高
    select * from tableA a where
    a.id < (select count(1) from tableA where id=a.id)
    and a.id>500
    and a.lx = '2b'

                  

    三、使用select的时候少用*,多敲敲键盘,写上字段名吧,因为ORACLE的查询器会把*转换为表的全部列名,这个会浪费时间的,所以在大表中少用

              

    四、充分利用rowid ,可以用rowid来分页,删除查询重复记录,很强大的,给两个例子:

    --oracle查找重复记录
    select * from tableA a where a.rowid>=(select min(rowid) from tableB b where a.column=b.column)


    --oracle删除重复记录
    delete from tableA a where a.rowid>=(select min(rowid) from tableB b where a.column=b.column)


    --分页 start=10 limit=10
    --end 为 start + limit
    --1.查询要排列的表A
    --2.查询A表的Rownum找出小于end的数据组成表B
    --3.查询B表通过rownum找出大于start的数据完成
    --简单的说先根据end值过滤数据,然后在根据start过滤数据
    SELECT * FROM
    (SELECT a.*, ROWNUM rn FROM (SELECT * FROM uim_serv_file_data ORDER BY OUID) a where ROWNUM<=20) b
    where rn>10 order by ouid desc

         

    五、存储过程中需要注意的,多用commit了,既可以释放资源,但是要谨慎。

              

    六、减少对数据库表的查询,这个很重要,能减少就减少,因为在执行语句的时候oracle会做很多初始工作。

              

    七、少用in,多用exists来代替

    --NO.1  IN的写法  
    SELECT * FROM TABLEA A WHERE
    A.ID IN (SELECT ID FORM TABLEB B WHERE B.ID>1)

    --NO.2 exists 写法
    SELECT * FROM TABLEA A WHERE
    EXISTS (SELECT 1 FROM TABLEB B WHERE A.ID=B.ID AND B.ID>1)




    来源:http://www.cnblogs.com/linjiqin/archive/2011/04/13/2014818.html
  • 相关阅读:
    Exchange 2013与 Office Web Apps 整合
    SharePoint2013 以其他用户登录和修改AD域用户密码 功能
    sharepoint 2010 自定义页面布局
    sharepoint 2010 记录管理 对象模型
    SharePoint2010 对象模型 关联列表
    在SharePoint Server 2010中更改“我的网站”
    xenapp 6.5 客户端插件第一次安装总是跳到官网
    如何解决在Windows Server 2008 R2 上安装证书服务重启后出现 CertificationAuthority 91错误事件
    在Win7 Hyper-v虚拟机中挂接真实机的声卡
    win8 中如何删除 共享文件夹 用户名和密码
  • 原文地址:https://www.cnblogs.com/kongxc/p/9383874.html
Copyright © 2020-2023  润新知