问题描述:刚开始做项目的时候没啥感觉,只用能出来结果,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. flask框架----flask-script组件

    Flask Script扩展提供向Flask插入外部脚本的功能,包括运行一个开发用的服务器,一个定制的Python shell,设置数据库的脚本,cronjobs,及其他运行在web应用之外的命令行任 ...

  2. MyEclipse如何清除废弃的工作空间

    1.MyEclipse如何清除废弃的工作空间Windows--->Preferences--->General--->Startup and Shutdown--->Works ...

  3. JAVA连接数据库 #03# HikariCP

    索引 为什么用数据库连接池? HikariCP快速入门 依赖 简单的草稿程序 设置连接池参数(只列举常用的) MySQL配置 修改Java连接数据库#02#中的代码 测试 为什么用数据库连接池? 为什 ...

  4. Eloquent JavaScript #10# Modules

    索引 Notes 背景问题 模块Modules 软件包Packages 简易模块 Evaluating data as code CommonJS modules ECMAScript modules ...

  5. 深度挖掘,Html5的 Range 滑动刻度的坑,兼容全平台,将任性进行到底!

    最近2天一直在弄一个滑动的刻度效果,由于项目是基于Web App开发的,于是考虑到 移动端和pc端 的兼容性问题,考虑的比较多,尝试采用 Html5的Range 来做,目前已经兼容 pc端和移动端! ...

  6. 论文阅读笔记 Improved Word Representation Learning with Sememes

    论文阅读笔记 Improved Word Representation Learning with Sememes 一句话概括本文工作 使用词汇资源--知网--来提升词嵌入的表征能力,并提出了三种基于 ...

  7. NLTK 知识整理

    NLTK 知识整理 nltk.corpus模块自带语料 NLTK comes with many corpora, toy grammars, trained models, etc. A compl ...

  8. python之路-day1-while循环

    while Thue: (条件为真无限循环)  break(跳出循环) 猜年龄: #Author:zwwage_of_jay = 40count = 0while count < 3: gues ...

  9. 使用Http协议Post上传文件

    转载:http://www.cnblogs.com/softidea/p/5745369.html 转载:https://blog.csdn.net/huanongying131/article/de ...

  10. FireMonkey 源码学习(4)

    (4)DoDrawLayout DoDrawLayout函数的源代码分析如下: procedure TTextLayoutNG.DoDrawLayout(const ACanvas: TCanvas) ...