问题描述:刚开始做项目的时候没啥感觉,只用能出来结果,sql随便写,但是后来用户的数据量达到几万条是,在访问系统,发现很多功能加载都很慢,有的页面一个简单的关联

查询居然要花费30多秒,实在是不能忍,所以自己研究了一下sql优化技巧,特此记录一下:

1. exists和in的使用

参考文档:https://www.cnblogs.com/liyasong/p/sql_in_exists.html

(1) exists是用循环(loop)的方式,由outer表的记录数决定循环的次数,所以,外表的记录数少,适合用exists;

用法:EXISTS后面跟一个子查询,当该查询可以查询出至少一条记录时返回真(not为不存在)

SELECT *
FROM t_f_hz t1
WHERE EXISTS
(SELECT f_hz_id
FROM T_F_T_POSSIBLELIST t2
WHERE f_hz_id = t1.pk_id and f_hz_id = 1);

(2) in先执行子查询,子查询的返回结果去重之后,在执行主查询,所以,子查询的返回结果越少,越适合用该方式。

SELECT *
FROM prj
WHERE f_name IN (SELECT f_name
FROM POSSIBLELIST
WHERE f_hz_id = '');

  这个查询语句中,当表中possiblelist查询出来的数据较少时,使用in,此时会将possiblelist表中查询出来的数据数量n(假设)

和prj表中的数据m(假设)做一个笛卡尔积,共(m*n)条数据,然后在查找出符合条件的数据。

  如果prj中数据较少时,应该使用exists,此时会先查询主表prj,然后用表中的每一条数据依次去判断where后面的条件是否成立,

如果成立则返回true不成立则返回false。如果返回的是true的话,则该行结果保留,如果返回的是false的话,则删除该行,最后将得到的结果返回。

exists (SELECT f_name
   FROM POSSIBLELIST
  WHERE f_hz_id = '');

总结:如果两个表一个较大,一个较小,则子查询大的用exists,子查询小的用in。

当只显示一个表的数据(只显示prj表的数据),关系条件只有一个where f_name in ()时用in比较合适。

当只显示一个表的数据,关系条件不止一个,此时使用in就不方便了,可以使用exists。

SELECT *
FROM t1
WHERE EXISTS
(SELECT fk_id
FROM t2
WHERE f_hz_id = t1.f_hz_id AND f_pac_id = t1.f_pac_id)

(3)not in 和not exists:

  如果查询语句使用了not in 那么内外表都进行全表扫描,没有用到索引;而not extsts 的子查询依然能用到表上的索引。

所以无论那个表大,用not exists都比not in要快。

2. is null和is not null优化

where子句中的is null和is not null将不会使用索引而是进行全表搜索,因此需要通过改变查询方式,分情况讨论等办法,去掉

where子句中的is null和is not null改为 A >0 或者 A> ' '。

select * from t1 where fk_pid is null
--优化如下:将为空的字段转为不为空的值(确保数据中是不会出现1)
select * from t1 where nvl(fk_pid,'') = '' select * from t1 where fk_pid is null
--优化如下:
select * from t1 where fk_pid = nvl(fk_pid,'')

3. 多张表关联查询优化

参考文档:https://www.cnblogs.com/liuyitian/p/5249597.html

       https://blog.csdn.net/tanga842428/article/details/52265991

(1) 多张表关联查询中,将数据量小的表写在from的最右边。

原因:oracle在解析sql语句的时候对from子句后面的表名是从右往左解析的,是先扫描最右边的表,

  然后在扫描左边的表,然后用左边的表匹配数据,匹配成功后就合并。在RBO优化器模式下,表应按结果记录数从大到小的顺序从左到右来排列,

因为表间连接时,最右边的表会被放到嵌套循环的最外层。最外层的循环次数越少,效率越高。

如果有3个以上的表连接查询,那就需要将交叉表(中间表)放到最右边。

-- 6484500条 282ms
select count(*) from t1, t2; --6484500 400ms
select count(*) from t2,t1; --64845 60ms
select count(*) from t1; --100 55ms
select count(*) from t2;

(2) where子句连接顺序

oracle采用自下而上的顺序解析where子句,根据这个原理,表之间的连接必须写在其他WHERE条件之前,

那些可以过滤掉最大数量记录的条件必须写在where子句的末尾。但是网上有很多中说法,有的说是过滤

最大数据量的条件放在最右边,也有的说是放在最左边。但是根据自己的测试结果,感觉放在最左边和最右边对性能影响不是很大。

3. 模糊查询like优化

oracle内部对instr进行了优化处理。

select * from table_hz hz where instr(hz.f_name,#{f_name,jdbcType=VARCHAR})>0

4.distinct优化

distinct在查询中经常用来去重,



 

oracle中sql优化的更多相关文章

  1. 对oracle中SQL优化的理解

    Oracle数据库里SQL优化的终极目标就是要缩短目标SQL语句的执行时间.要达到上述目的,我们通常只有如下三种方法可以选择:1.降低目标SQL语句的资源消耗.2.并行执行目标SQL语句.3.平衡系统 ...

  2. oracle中sql语句的优化

    oracle中sql语句的优化 一.执行顺序及优化细则 1.表名顺序优化 (1) 基础表放下面,当两表进行关联时数据量少的表的表名放右边表或视图: Student_info   (30000条数据)D ...

  3. 基于Oracle的SQL优化(社区万众期待 数据库优化扛鼎巨著)

    基于Oracle的SQL优化(社区万众期待数据库优化扛鼎巨著) 崔华 编   ISBN 978-7-121-21758-6 2014年1月出版 定价:128.00元 856页 16开 编辑推荐 本土O ...

  4. 读书笔记-《基于Oracle的SQL优化》-第一章-3

    优化器: 1.优化器的模式: 用于决定在Oracle中解析目标SQL时所用优化器的类型,以及决定当使用CBO时计算成本值的侧重点.这里的“侧重点”是指当使用CBO来计算目标SQL各条执行路径的成本值时 ...

  5. 基于oracle的sql优化

    [基于oracle的sql优化] 基于oracle的sql优化 [博主]高瑞林 [博客地址]http://www.cnblogs.com/grl214 一.编写初衷描述 在应有系统开发初期,由于数据库 ...

  6. Oracle之SQL优化专题01-查看SQL执行计划的方法

    在我2014年总结的"SQL Tuning 基础概述"中,其实已经介绍了一些查看SQL执行计划的方法,但是不够系统和全面,所以本次SQL优化专题,就首先要系统的介绍一下查看SQL执 ...

  7. 转://从一条巨慢SQL看基于Oracle的SQL优化

    http://mp.weixin.qq.com/s/DkIPwbDKIjH2FMN13GkT4w 本次分享的内容是基于Oracle的SQL优化,以一条巨慢的SQL为例,从快速解读SQL执行计划.如何从 ...

  8. 从一条巨慢SQL看基于Oracle的SQL优化(重磅彩蛋+PPT)

    本文根据DBAplus社群第110期线上分享整理而成,文末还有好书送哦~ 讲师介绍 丁俊 新炬网络首席性能优化专家 SQL审核产品经理 DBAplus社群联合发起人.<剑破冰山-Oracle开发 ...

  9. Oracle中CBO优化器简介

    Oracle中CBO优化器简介 Oracle数据库中的优化器是SQL分析和执行的优化工具.它负责制定SQL的执行计划,也就是它负责保证SQL的执行计划的效率最高,比如优化器决定Oracle以什么样的方 ...

随机推荐

  1. 解决Win 10上SSD缓慢问题

    标准硬盘驱动器(HDD)由于其高存储容量和低成本而长期以来一直是计算机的主要存储设备.固态硬盘(SSD)是另一种存储解决方案,正在逐步取代大多数硬盘驱动器.但是,随着时间的推移,SSD会因各种原因而大 ...

  2. flask框架----蓝图

    蓝图(flask中多py文件拆分都要用到蓝图) 如果代码非常多,要进行归类.不同的功能放在不同的文件,吧相关的视图函数也放进去.蓝图也就是对flask的目录结构进行分配(应用于小,中型的程序), 小中 ...

  3. 使用Holer远程桌面登录家里电脑和公司内网电脑

    1. Holer工具简介 Holer exposes local servers behind NATs and firewalls to the public internet over secur ...

  4. MyBatis的核心配置、动态sql、关联映射(快速总结)

    MyBatis的核心对象和配置 #1. SqlSessionFactory对象: 单个数据库映射关系经过编译的内存镜像: 作用:创建SQLSession对象. //读取配置文件 InputSteam ...

  5. springMVC之一(页面<--->控制器 互相传值,转发和重定向)

    #页面--->控制器1.request:不建议使用2.使用属性传值(建议使用)@RequestParam("name") String username3.使用Bean对象传 ...

  6. 从零开始部署一个 Laravel 站点

    从零开始部署一个 Laravel 站点 此文章为原创文章,未经同意,禁止转载. PHP Laravel Web Git 在阿里云买ECS的时候选择自己习惯的镜像系统,我一般都是使用Linux Ubun ...

  7. 【python35.2--图形用户界面EasyGui】

    一.猜字游戏 #猜字游戏(从1到10) import easygui as g import random g.msgbox('欢迎进入探险之路!') screct = random.randint( ...

  8. VS2015密钥

    Visual Studio Professional 2015简体中文版(专业版)KEY:HMGNV-WCYXV-X7G9W-YCX63-B98R2Visual Studio Enterprise 2 ...

  9. Flask学习【第8篇】:flask-session组件

    简介 flask-session是flask框架的session组件,由于原来flask内置session使用签名cookie保存,该组件则将支持session保存到多个地方,如 redis:保存数据 ...

  10. P1337 [JSOI2004]平衡点 / 吊打XXX 模拟退火

    链接 https://www.luogu.org/problemnew/show/P1337 思路 交了好多发,都是wrong 初始值取平均数就1A了 真的是玄学的算法 代码 // luogu-jud ...