Oracle SQL调优
在多数情况下,Oracle使用索引t来更快地遍历表,优化器主要根据定义的索引来提高性能。
但是,如果在SQL语句的where子句中写的SQL代码不合理,就会造成优化器删去索引而使用全表扫描,一般就这种SQL语句就是所谓的劣质SQL语句。
在编写SQL语句时我们应清楚优化器根据何种原则来删除索引,这有助于写出高性能的SQL语句
1. IS NULL 与 IS NOT NULL
不能用null作索引,任何包含null值的列都将不会被包含在索引中。
即使索引有多列这样的情况下,只要这些列中有一列含有null,该列就会从索引中排除。
也就是说如果某列存在空值,即使对该列建索引也不会提高性能。
任何在where子句中使用is null或is not null的语句优化器是不允许使用索引的
如果我们必须要用 is null,又需要提供查询效率 可以用函数索引
实例如下
create table test_date (name varchar2(),day date); insert into test_date(name ,day) values ('lucy',null); insert into test_date(name ,day) values ('jony',null); insert into test_date(name,day) values ('james',sysdate); select * from test_date; --创建decode函数索引来代替 create index finx_day on test_date(decode(day,null,'N', 'Y')) --使用decode判断来代替is null判断 select * from test_date a where decode(day,null,'N','Y') = 'N'
2. 联接列
对于有联接的列,即使最后的联接值为一个静态值,优化器是不会使用索引的。
假定有一个职工表(employee),对于一个职工的姓和名分成两列存放(FIRST_NAME和LAST_NAME),
现在要查询一个叫比尔.克林顿(Bill Cliton)的职工。
下面是一个采用联接查询的SQL语句,
select * from employs where first_name||’ ’||last_name ='Beill Cliton'
上面这条语句完全可以查询出是否有Bill Cliton这个员工,但是这里需要注意,系统优化器对基于last_name创建的索引没有使用。
当采用下面这种SQL语句的编写,Oracle系统就可以采用基于last_name创建的索引。
Select * from employee where first_name ='Beill' and last_name ='Cliton'
如果一个变量(name)中存放着Bill Cliton这个员工的姓名,对于这种情况我们又如何避免全程遍历?
可以使用一个函数,将变量name中的姓和名分开就可以了,但是有一点需要注意,这个函数是不能作用在索引列上。‘
下面是SQL查询脚本
select * from employee where first_name = SUBSTR(,INSTR() and last_name = SUBSTR('&&name',INSTR('&&name’,' ')+1)
3. 带通配符(%)的like语句
以如下SQL讲解:
select * from employee where last_name like '%cliton%'
这里由于通配符(%)在搜寻词首出现,所以Oracle系统不使用last_name的索引。
在很多情况下可能无法避免这种情况,但是一定要心中有底,通配符如此使用会降低查询速度。
然而当通配符出现在字符串其他位置时,优化器就能利用索引。
在下面的查询中索引得到了使用:
select * from employee where last_name like 'c%'
读者注意:项目真实开发中,如果经常性的模糊查询,可以采用solr或者elasticSearch或者直接Lucene也可以
4. Order by语句
ORDER BY语句决定了Oracle如何将返回的查询结果排序。
Order by语句对要排序的列没有什么特别的限制,也可以将函数加入列中(联接或者附加等)。
任何在Order by语句的非索引项或者有计算表达式都将降低查询速度。
仔细检查order by语句以找出非索引项或者表达式,它们会降低性能。
解决这个问题的办法就是重写order by语句以使用索引,也可以为所使用的列建立另外一个索引,同时应绝对避免在order by子句中使用表达式。
5. NOT 的理想替代方案
我们在查询时经常在where子句使用一些逻辑表达式,如大于、小于、等于以及不等于等等,
也可以使用and(与)、or(或)以及not(非)。NOT可用来对任何逻辑运算符号取反。
下面是一个NOT子句的例子:
... where not (status ='VALID')
如果要使用NOT,则应在取反的短语前面加上括号,并在短语前面加上NOT运算符。
NOT运算符包含在另外一个逻辑运算符中,这就是不等于(<>;)运算符。
换句话说,即使不在查询where子句中显式地加入NOT词,NOT仍在运算符中,
见下例:
... where status <>'INVALID'
再看下面这个例子:
;
对这个查询,可以改写为不使用NOT:
or salary>;
虽然这两种查询的结果一样,但是第二种查询方案会比第一种查询方案更快些。第二种查询允许Oracle对salary列使用索引,而第一种查询则不能使用索引。
6. IN和EXISTS(下面有个重复的)
有时候会将一列和一系列值相比较。最简单的办法就是在where子句中使用子查询。在where子句中可以使用两种格式的子查询。
第一种格式是使用IN操作符:
... where column in(select * from ... where ...);
第二种格式是使用EXIST操作符:
... where exists (select 'X' from ...where ...);
我相信绝大多数人会使用第一种格式,因为它比较容易编写,而实际上第二种格式要远比第一种格式的效率高。
在Oracle中可以几乎将所有的IN操作符子查询改写为使用EXISTS的子查询。
第二种格式中,子查询以‘select 'X'开始。运用EXISTS子句不管子查询从表中抽取什么数据它只查看where子句。
这样优化器就不必遍历整个表而仅根据索引就可完成工作(这里假定在where语句中使用的列存在索引)。
相对于IN子句来说,EXISTS使用相连子查询,构造起来要比IN子查询困难一些。
通过使用EXIST,Oracle系统会首先检查主查询,然后运行子查询直到它找到第一个匹配项,这就节省了时间。
Oracle系统在执行IN子查询时,首先执行子查询,并将获得的结果列表存放在在一个加了索引的临时表中。
在执行子查询之前,系统先将主查询挂起,待子查询执行完毕,存放在临时表中以后再执行主查询。这也就是使用EXISTS比使用IN通常查询速度快的原因。
同时应尽可能使用NOT EXISTS来代替NOT IN,尽管二者都使用了NOT(不能使用索引而降低速度),NOT EXISTS要比NOT IN查询效率更高
7、Select子句中避免使用 “ * ”:
当你想在select子句中列出所有的column时,使用动态SQL列引用 ‘*' 是一个方便的方法。
不幸的是,这是一个非常低效的方法。
实际上,ORACLE在解析的过程中,会将 '*' 依次转换成所有的列名, 这个工作是通过查询数据字典完成的, 这意味着将耗费更多的时间。
8、减少访问数据库的次数:
当执行每条SQL语句时,ORACLE在内部执行了许多工作:
解析SQL语句、估算索引的利用率、绑定变量、读数据块等等。
由此可见,减少访问数据库的次数,就能实际上减少ORACLE的工作量。
举例:
题目——我要查找编号为0001、0002学生的信息。
(低效)
'; ';
(高效)
';
9、使用Decode函数来减少处理时间:
使用DECODE函数可以避免重复扫描相同记录或重复连接相同的表。
举例:
(低效)
' and name like 'anger%'; ' and name like 'anger%';
(高效)
','XYZ',null)) count_02, sum(decode(dept_id,',dept_id,null)) sum_02 from table1 where name like 'anger%';
10、整合简单,无关联的数据库访问:
如果你有几个简单的数据库查询语句,你可以把它们整合到一个查询中(即使它们之间没有关系)
举例:
(低效)
'; '; ';
(高效)
select t1.name, t2.name, t3.name from table1 t1, table2 t2, table3 t3 '
注:上面例子虽然高效,但是可读性差,需要量情而定啊!
11、删除重复记录:
最高效的删除重复记录方法 ( 因为使用了ROWID)
举例:
delete from table1 t1 where t1.rowid > (select min(t2.rowid) from table1 t2 where t1.id = t2.id);
12、尽量不要使用having子句,可以考虑用where替换:
having只会在检索出所有记录之后才对结果集进行过滤. 这个处理需要排序,总计等操作。
如果能通过where子句限制记录的数目,那就能减少这方面的开销。
13、尽量用表的别名:
当在SQL语句中连接多个表时,请使用表的别名并把别名前缀于每个Column上。
这样一来,就可以减少解析的时间并减少那些由Column歧义引起的语法错误。
14、用exists替换distinct:
当提交一个包含一对多表信息的查询时,避免在select子句中使用distinct. 一般可以考虑用exists替换
举例:
(低效)
select distinct d.dept_no, d.dept_name from t_dept d, t_emp e where d.dept_no = e.dept_no;
(高效)
from t_emp where d.dept_no = e.dept_no);
exists使查询更为迅速,因为RDBMS核心模块将在子查询的条件一旦满足后,立刻返回结果.
15、用表连接替换exists:
通常来说,采用表连接的方式比exists更有效率。
举例:
(低效)
from dept where dept_no = e.dept_no and dept_cat = 'W');
(高效)
select ename from dept d, emp e where e.dept_no = d.dept_no and dept_cat = 'W';
Oracle SQL调优的更多相关文章
- Oracle SQL 调优健康检查脚本
Oracle SQL 调优健康检查脚本 我们关注数据库系统的性能,进行数据库调优的主要工作就是进行SQL的优化.良好的数据架构设计.配合应用系统中间件和写一手漂亮的SQL,是未来系统上线后不出现致命性 ...
- Oracle SQL调优记录
目录 一.前言 二.注意点 三.Oracle执行计划 四.调优记录 @ 一.前言 本博客只记录工作中的一次oracle sql调优记录,因为数据量过多导致的查询缓慢,一方面是因为业务太过繁杂,关联了太 ...
- Oracle SQL调优之分区表
目录 一.分区表简介 二.分区表优势 三.分区表分类 3.1 范围分区 3.2 列表分区 3.3 散列分区 3.4 组合分区 四.分区相关操作 五.分区相关查询 附录:分区表索引失效的操作 一.分区表 ...
- Oracle SQL调优系列之SQL Monitor Report
@ 目录 1.SQL Monitor简介 2.捕捉sql的前提 3.SQL Monitor 参数设置 4.SQL Monitor Report 4.1.SQL_ID获取 4.2.Text文本格式 4. ...
- Oracle SQL调优之表设计
在看<收获,不止sql优化>一书,并做了笔记,本博客介绍一下一些和调优相关的表比如分区表.临时表.索引组织表.簇表以及表压缩技术 分区表使用与查询频繁而更新数据不频繁的情况,不过要记得加全 ...
- Oracle SQL 调优之 sqlhc
SQL 执行慢,如何 快速准确的优化. sqlhc 就是其中最好工具之一 通过获得sql所有的执行计划,列出实际的性能的瓶颈点,列出 sql 所在的表上的行数,每一列的数据和分布,现有的索引,sql ...
- Oracle SQL调优之绑定变量用法简介
目录 一.SQL执行过程简介 二.绑定变量典型用法 2.1.在SQL中绑定变量 2.2.在PL/SQL中使用绑定变量 2.3.PL/SQL批量绑定变量 2.4.Java代码里使用绑定变量 最近在看&l ...
- ORACLE SQL调优案例一则
收到监控告警日志文件(Alert)的作业发出的告警邮件,表空间TEMPSCM2不能扩展临时段,说明临时表空间已经被用完了,TEMPSCM2表空间不够用了 Dear All: The Instanc ...
- Oracle中SQL调优(SQL TUNING)之最权威获取SQL执行计划大全
该文档为根据相关资料整理.总结而成,主要讲解Oracle数据库中,获取SQL语句执行计划的最权威.最正确的方法.步骤,此外,还详细说明了每种方法中可选项的意义及使用方法,以方便大家和自己日常工作中查阅 ...
随机推荐
- 轻松学习JVM——垃圾回收器
原文链接:https://www.cnblogs.com/leefreeman/p/7402695.html 上一篇我们介绍了常见的垃圾回收算法,不同的算法各有各的优缺点,在JVM中并不是单纯的使用某 ...
- mfc static控件 视频播放 闪屏问题 解决方案
方案1: 我昨天刚在csdn上解决了这个问题,不是双缓冲和WS_CLIPCHILDREN还有背景擦出什么的问题,就是在你重画的时候要去掉这些控件(按钮什么的)区域, 闪屏是因为窗口大小发生改变时,由于 ...
- 关于java实现断点续传的上传下载功能问题
在web项目中上传文件夹现在已经成为了一个主流的需求.在OA,或者企业ERP系统中都有类似的需求.上传文件夹并且保留层级结构能够对用户行成很好的引导,用户使用起来也更方便.能够提供更高级的应用支撑. ...
- UVa 11212 Editing a Book (IDA* && 状态空间搜索)
题意:你有一篇n(2≤n≤9)个自然段组成的文章,希望将它们排列成1,2,…,n.可以用Ctrl+X(剪切)和Ctrl+V(粘贴)快捷键来完成任务.每次可以剪切一段连续的自然段,粘贴时按照顺序粘贴.注 ...
- LBS 基于位置的服务
LBS (Location Based Services)基于位置的服务 基于位置的服务,它是通过电信移动运营商的无线电通讯网络(如GSM网.CDMA网)或外部定位方式(如GPS)获取移动终端用户的位 ...
- (四)mysql -- 常用函数
今天get一个,先记录一下 以后慢慢补充~ 将varchar转换成int 例如:select * from tb_1 order by cast(sport_sum as unsigned integ ...
- sqli-labs(12)
0X01摘要体现(小编这里傻逼了 可以直接用group_concat函数绕过显示问题我还在用limit绕过) 还是这个模块 我们很熟徐那么先来尝试一下 单引号加入 无报错信息 哦豁 加入双引号试试呐 ...
- 大数据笔记(二十二)——大数据实时计算框架Storm
一. 1.对比:离线计算和实时计算 离线计算:MapReduce,批量处理(Sqoop-->HDFS--> MR ---> HDFS) 实时计算:Storm和Spark Sparki ...
- vue基于element-ui的三级CheckBox复选框
最近vue项目需要用到三级CheckBox复选框,需要实现全选反选不确定三种状态.但是element-ui table只支持多选行,并不能支持三级及以上的多选,所以写了这篇技术博文供以后学习使用. 效 ...
- CNN中感受野的理解
本文摘自看完还不懂卷积神经网络“感受野”?那你来找我 作者:程序_小白链接:https://www.jianshu.com/p/9305d31962d8 一.到底什么是“感受野”(接受野Recepti ...