zoukankan      html  css  js  c++  java
  • 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)
    复制代码
  • 相关阅读:
    Atitti 图像处理 图像混合 图像叠加 blend 原理与实现
    Atitit Gaussian Blur 高斯模糊 的原理and实现and 用途
    Atitit 图像处理 灰度图片 灰度化的原理与实现
    Atitit (Sketch Filter)素描滤镜的实现  图像处理  attilax总结
    Atitit 实现java的linq 以及与stream api的比较
    Atitit attilax在自然语言处理领域的成果
    Atitit 图像处理 常用8大滤镜效果 Jhlabs 图像处理类库 java常用图像处理类库
    Atitit 图像处理--图像分类 模式识别 肤色检测识别原理 与attilax的实践总结
    Atitit apache 和guava的反射工具
    atitit。企业的价值观 员工第一 vs 客户第一.docx
  • 原文地址:https://www.cnblogs.com/dfyg-xiaoxiao/p/7213769.html
Copyright © 2011-2022 走看看