1.选择最有效率的表名顺序(只在基于规则的优化器中有效):

oracle的解析器按照从右到左的顺序处理 from 子句中的表名,from子句中写在最后的表(基础表driving table)将被最先处理,在 from 子句中包含多个表的情况下, 你必须选择记录条数最少的表作为基础表。如果有 3 个以上的表连接查询, 那就需 要选择交叉表(intersection table)作为基础表, 交叉表是指那个被其他表所引用的表.

2.where子句中的连接顺序:

oracle 采用自下而上的顺序解析where子句,根据这个原理,表之间的连接必须写 在其他where条件之前, 那些可以过滤掉最大数量记录的条件必须写在where子句的末尾.

3.select子句中避免使用 ‘ * ‘:

oracle在解析的过程中, 会将'*' 依次转换成所有的列名, 这个工作是通过查询数 据字典完成的, 这意味着将耗费更多的时间.

4.减少访问数据库的次数:

oracle在内部执行了许多工作: 解析 SQL 语句, 估算索引的利用率, 绑定变量,读数据块等

5.在 SQL*Plus , SQL*Forms 和 Pro*C 中重新设置arraysize参数, 可以增加每 次数据库访问的检索数据量 ,建议值为200

6.使用 decode函数来减少处理时间:

使用 decode函数可以避免重复扫描相同记录或重复连接相同的表.

7.删除重复记录:

最高效的删除重复记录方法 ( 因为使用了 rowid)例子:

delete from  emp e  where

e.rowid > (select min(x.rowid)

from emp x where x.emp_no=e.emp_no);

8.整合简单,无关联的数据库访问:

如果你有几个简单的数据库查询语句,你可以把它们整合到一个查询中(即使它们之 间没有关系)

9.用truncate替代delete:

当删除表中的记录时,在通常情况下, 回滚段(rollback segments ) 用来存放可以被恢复的信息.

如果你没有commit事务,oracle会将数据恢复到删除之前的状态(准确 地说是恢复到执行删除命令之前的状况) 而当运用truncate时, 回滚段不再存放 任何可被恢复的信息.当命令运行后,数据不能被恢复.因此很少的资源被调用,执行时 间也会很短. (译者按: truncate只在删除全表适用,truncate 是 DDL 不是DML) .

10.尽量多使用 commit:

只要有可能,在程序中尽量多使用 commit, 这样程序的性能得到提高,

需求也会因为 commit所释放的资源而减少:

commit所释放的资源:

a. 回滚段上用于恢复数据的信息.

b. 被程序语句获得的锁

c. redo log buffer 中的空间

d. oracle为管理上述 3 种资源中的内部花费

11.用 where子句替换having子句:  避免使用 having子句, having只会在检索出所有记录之后才对结果集进行过滤. 这个处理需要排序,总计等操作. 如果能通过 where子句限制记录的数目,那就能减 少这方面的开销. (非 oracle 中)on、where、having 这三个都可以加条件的子句中, on 是最先执行,where 次之,having 最后,因为 on 是先把不符合条件的记录过滤后 才进行统计,它就可以减少中间运算要处理的数据,按理说应该速度是最快的,where 也应该比 having 快点的,因为它过滤数据后才进行 sum,在两个表联接时才用 on 的,所以在一个表的时候,就剩下 where 跟 having 比较了。在这单表查询统计的情 况下,如果要过滤的条件没有涉及到要计算字段,那它们的结果是一样的,只是 where 可以使用rushmore 技术,而 having 就不能,在速度上后者要慢如果要涉及到 计算的字段,就表示在没计算之前,这个字段的值是不确定的,根据上篇写的工作 流程,where 的作用时间是在计算之前就完成的,而having 就是在计算后才起作用 的,所以在这种情况下,两者的结果会不同。在多表联接查询时,on 比where 更早 起作用。系统首先根据各个表之间的联接条件,把多个表合成一个临时表后,再由 where 进行过滤,然后再计算,计算完后再由 having 进行过滤。由此可见,要想过 滤条件起到正确的作用,首先要明白这个条件应该在什么时候起作用,然后再决定,放在那里.

12.减少对表的查询:

在含有子查询的 SQL 语句中,要特别注意减少对表的查询.例子:

select tablename from tables

where (tab_name,db_ver)=(select tab_name,db_ver from tab_colimns

where version =604)

13.通过内部函数提高 SQL 效率.:

复杂的 SQL 往往牺牲了执行效率. 能够掌握上面的运用函数解决问题的方法在实际 工作中是非常有意义的 .

14.使用表的别名(Alias):

当在 SQL 语句中连接多个表时, 请使用表的别名并把别名前缀于每个 column 上.这 样一来,就可以减少解析的时间并减少那些由 column 歧义引起的语法错误.

15.用 exists替代 in、用 not exists 替代not in:

在许多基于基础表的查询中,为了满足一个条件,往往需要对另一个表进行联接,在这种情况下, 使用exists(或not exists )通常将提高查询的效率. 在子查询中,not in子句将执行一个内部的排序和合并. 无论在哪种情况下,not in都是最低效的 (因为它对子查询中的表执行了一个全表遍历). 为了避免使用 not in ,我们可以把它改写成 外连接(Outer Joins)或not exists。

例子:

(高效)

select # from emp where

empno>0 and exists

(select 'x' from dept where dept.deptno =emp.deptno and loc='melb')

(低效)

select  * from emp where empno>0 and deptno in

(select deptno dept where loc='melb')

16.识别'低效执行'的 SQL 语句:  虽然目前各种关于SQL优化的图形化工具层出不穷,但是写出自己的SQL工具来解决 问题始终是一个最好的方法:

select  executions , disk_reads, buffer_gets,

round((buffer_gets-disk_reads)/buffer_gets,2) hit_radio,

round(disk_reads/executions,2) reads_per_run,

sql_text  from  v$sqlarea  where

executions>0  and  buffer_gets > 0  and

(buffer_gets-disk_reads)/buffer_gets < 0.8

order by  4 desc;

17.用索引提高效率:

索引是表的一个概念部分,用来提高检索数据的效率,oracle使用了一个复杂的自 平衡B-tree结构. 通常,通过索引查询数据比全表扫描要快. 当oracle找出执行查询 和 update 语句的最佳路径时, oracle优化器将使用索引. 同样在联结多个表时使用 索引也可以提高效率. 另一个使用索引的好处是,它提供了主键(primary key)的唯一 性验证.。那些 long或long raw数据类型, 你可以索引几乎所有的列. 通常, 在大 型表中使用索引特别有效. 当然,你也会发现, 在扫描小表时,使用索引同样能提高效 率. 虽然使用索引能得到查询效率的提高,但是我们也必须注意到它的代价. 索引需 要空间来存储,也需要定期维护, 每当有记录在表中增减或索引列被修改时, 索引本 身也会被修改. 这意味着每条记录的 insert delete update将为此多付出4 , 5 次 的磁盘 I/O . 因为索引需要额外的存储空间和处理,那些不必要的索引反而会使查询 反应时间变慢.。定期的重构索引是有必要的:  alter index <indexname> rebuild <tablespacename>

18.用 exists替换 distinct:  当提交一个包含一对多表信息(比如部门表和雇员表)的查询时,避免在select子句中 使用 distinct. 一般可以考虑用 EXIST 替换, EXISTS 使查询更为迅速,因为RDBMS核 心模块将在子查询的条件一旦满足后,立刻返回结果.

例子:

(低效):

select  distinct  dept_no,dept_name  from  dept d , emp e  where

d.dept_no = e.dept_no

(高效):

select dept_no,dept_name

from  dept d

where

exists ( select ‘x'  from emp e where e.dept_no = d.dept_no);

19.sql 语句用大写的;因为 oracle 总是先解析 sql 语句,把小写的字母转换成大 写的再执行

20.在 java 代码中尽量少用连接符“+”连接字符串!

21.避免在索引列上使用 not通常,   我们要避免在索引列上使用 not, not会产生在和在索引列上使用函数相同的影响. 当 oracle”遇到”not,他就会停止使用索引转而执行全表扫描.

22.避免在索引列上使用计算:

where子句中,如果索引列是函数的一部分.优化器将不使用索引而使用全表扫描.  举例:

低效:

select … from  dept  where sal * 12 > 25000;

高效:

select … from dept where sal > 25000/12;

23.用>=替代>

高效:  select * from  emp  where  deptno >=4

低效:  select * from emp where deptno >3

两者的区别在于, 前者 DBMS 将直接跳到第一个 dept等于 4 的记录而后者将首先定 位到 deptno =3 的记录并且向前扫描到第一个 dept大于 3 的记录.

24.用 union替换 or(适用于索引列)  通常情况下, 用 union 替换 where子句中的 or将会起到较好的效果.对索引列使用or将造成全表扫描. 注意, 以上规则只针对多个索引列有效. 如果有column没有 被索引, 查询效率可能会因为你没有选择 or而降低. 在下面的例子中, loc_id和 region上都建有索引.

高效:

select loc_id , loc_desc , region  from location

where loc_id = 10

union

select loc_id , loc_desc , region

from location

where region = “melbourne”

低效:

select loc_id , loc_desc , region  from location

where loc_id = 10 or region = “melbourne”

如果你坚持要用 or, 那就需要返回记录最少的索引列写在最前面.

25.用 in来替换or 这是一条简单易记的规则,但是实际的执行效果还须检验,两者的执行路径似乎是相同的.

低效:

select…. from location where loc_id = 10 or loc_id = 20 or loc_id = 30

高效

select… from location where loc_in  in (10,20,30);

26.避免在索引列上使用is null和is not null避免在索引中使用任何可以为空的列,oracle将无法使用该索引.对于单列索引, 如果列包含空值,索引中将不存在此记录. 对于复合索引,如果每个列都为空,索 引中同样不存在此记录. 如果至少有一个列不为空,则记录存在于索引中.举例: 如 果唯一性索引建立在表的A列和B列上, 并且表中存在一条记录的 A,B 值为 (123,null) , oracle将不接受下一条具有相同 A,B 值(123,null)的记录(插入). 然而如果所有的索引列都为空,oracle将认为整个键值为空而空不等于空. 因此你可以插 入 1000 条具有相同键值的记录,当然它们都是空! 因为空值不存在于索引列中,所以 where子句中对索引列进行空值比较将使 oracle停用该索引.

低效: (索引失效)

select … from  department  where  dept_code is not null;

高效: (索引有效)

select … from  department  where  dept_code >=0;

27.总是使用索引的第一个列:

如果索引是建立在多个列上, 只有在它的第一个列(leading column)被 where 子句引 用时,优化器才会选择使用该索引. 这也是一条简单而重要的规则,当仅引用索引的 第二个列时,优化器使用了全表扫描而忽略了索引.

28.用 union-all替换 union( 如果有可能的话):  当 SQL 语句需要 union 两个查询结果集合时,这两个结果集合会以 union-all的方 式被合并, 然后在输出最终结果前进行排序. 如果用 union-all替代union, 这样排序就不是必要了. 效率就会因此得到提高. 需要注意的是, union-all 将重复输出两 个结果集合中相同记录. 因此各位还是要从业务需求分析使用  union-all 的可行性. union将对结果集合排序,这个操作会使用到 sort_area_size 这块内存. 对于这块 内存的优化也是相当重要的. 下面的 SQL 可以用来查询排序的消耗量.

低效:

select  acct_num, balance_amt

from  debit_transactions

where tran_date = '31-dec-95'

union

select acct_num, balance_amt

from debit_transactions

where tran_date = '31-dec-95'

高效:

select acct_num, balance_amt

from debit_transactions

where tran_date = '31-dec-95'

union all

select acct_num, balance_amt

from debit_transactions

where tran_date = '31-dec-95'

29.用 where 替代order by:

order by 子句只在两种严格的条件下使用索引.

order by 中所有的列必须包含在相同的索引中并保持在索引中的排列顺序.

order by中所有的列必须定义为非空.

where 子句使用的索引和order by子句中所使用的索引不能并列.

例如:

表 dept包含以下列:

dept_code pk not null  dept_desc not null  dept_type null

低效:

(索引不被使用)

select dept_code from dept order by  dept_type

高效:

(使用索引)

select dept_code  from  dept  where  dept_type > 0

30.避免改变索引列的类型:

当比较不同数据类型的数据时, ORACLE 自动对列进行简单的类型转换.  假设 EMPNO 是一个数值类型的索引列.

select …  from emp  where  empno = ‘123'

实际上,经过 ORACLE 类型转换, 语句转化为:

select …  from emp  where  empno = to_number(‘123')

幸运的是,类型转换没有发生在索引列上,索引的用途没有被改变.

现在,假设 emp_type 是一个字符类型的索引列.

select …  from emp  where emp_type = 123

这个语句被oracle转换为:

select …  from emp  whereto_number(emp_type)=123

因为内部发生的类型转换, 这个索引将不会被用到!

为了避免oracle对你的SQL进 行隐式的类型转换, 最好把类型转换用显式表现出来. 注意当字符和数值比较时, oracle会优先转换数值类型到字符类型

31.需要当心的 where子句:  某些 select语句中的 where子句不使用索引.

这里有一些例子.  在下面的例子里,

(1)‘!=' 将不使用索引. 记住, 索引只能告诉你什么存在于表中, 而 不能告诉你什么不存在于表中.

(2) ‘||'是字符连接函数. 就象其他函数那样, 停用了 索引.

(3) ‘+'是数学函数. 就象其他数学函数那样, 停用了索引.

(4)相同的索引列不能 互相比较,这将会启用全表扫描.

32.

a. 如果检索数据量超过 30%的表中记录数.使用索引将没有显著的效率提高.

b. 在特定情况下, 使用索引也许会比全表扫描慢, 但这是同一个数量级上的区别. 而通常情况下,使用索引比全表扫描要块几倍乃至几千倍!

33.避免使用耗费资源的操作:  带有 distinct,union,minus,intersect,order by 的 SQL 语句会启动 SQL 引擎  执行耗费资源的排序(SORT)功能. distinct 需要一次排序操作, 而其他的至少需要执 行两次排序. 通常,带有union,minus,intersect 的 SQL 语句都可以用其他方式重 写. 如果你的数据库的 sort_area_size 调配得好, 使用union,minus,intersect  也是可以考虑的, 毕竟它们的可读性很强

34.优化 group by:  提高 group by 语句的效率, 可以通过将不需要的记录在group by  之前过滤掉.下 面两个查询返回相同结果但第二个明显就快了许多.

低效:

select job , avg(sal)  from emp

group by job

having job = ‘president'  or job = ‘manager'

高效:

select job , avg(sal)  from

emp  where job = ‘president'

or job = ‘manager'

group by job

sql 优化的更多相关文章

  1. SQL优化案例—— RowNumber分页

    将业务语句翻译成SQL语句不仅是一门技术,还是一门艺术. 下面拿我们程序开发工程师最常用的ROW_NUMBER()分页作为一个典型案例来说明. 先来看看我们最常见的分页的样子: WITH CTE AS ...

  2. SQL 优化总结

    SQL 优化总结 (一)SQL Server 关键的内置表.视图 1. sysobjects         SELECT name as '函数名称',xtype as XType  FROM  s ...

  3. (转)SQL 优化原则

    一.问题的提出 在应用系统开发初期,由于开发数据库数据比较少,对于查询SQL语句,复杂视图的的编写等体会不出SQL语句各种写法的性能优劣,但是如果将应用 系统提交实际应用后,随着数据库中数据的增加,系 ...

  4. sql优化阶段性总结以及反思

    Sql优化思路阶段性心得: 这段时间的优化做了好几个案例,其实有很多的类似点,都是好几张大表的相互连接,然后执行长达好几个小时,甚至都跑不出来. 自己差不多的思路就是Parallel full tab ...

  5. mysql sql优化实例

    mysql sql优化实例 优化前: pt-query-degist分析结果: # Query 3: 0.00 QPS, 0.00x concurrency, ID 0xDC6E62FA021C85B ...

  6. SQL优化技巧

    我们开发的大部分软件,其基本业务流程都是:采集数据→将数据存储到数据库中→根据业务需求查询相应数据→对数据进行处理→传给前台展示.对整个流程进行分析,可以发现软件大部分的操作时间消耗都花在了数据库相关 ...

  7. ORACLE常用SQL优化hint语句

    在SQL语句优化过程中,我们经常会用到hint,现总结一下在SQL优化过程中常见Oracle HINT的用法: 1. /*+ALL_ROWS*/ 表明对语句块选择基于开销的优化方法,并获得最佳吞吐量, ...

  8. SQL优化有偿服务

    本人目前经营MySQL数据库的SQL优化服务,100块钱一条.具体操作模式 其中第一条,可以通过在微信朋友圈转发链接中的信息(http://www.yougemysqldba.com/discuz/v ...

  9. 【MySQL】SQL优化系列之 in与range 查询

    首先我们来说下in()这种方式的查询 在<高性能MySQL>里面提及用in这种方式可以有效的替代一定的range查询,提升查询效率,因为在一条索引里面,range字段后面的部分是不生效的. ...

随机推荐

  1. webpack入门教程之初识loader(二)

    上一节我们学习了webpack的安装和编译,这一节我们来一起学习webpack的加载器和配置文件. 要想让网页看起来绚丽多彩,那么css就是必不可少的一份子.如果想要在应用中增加一个css文件,那么w ...

  2. 应用OpenMP的一个简单的设计模式

    小喵的唠叨话:最近很久没写博客了,一是因为之前写的LSoftmax后馈一直没有成功,所以在等作者的源码.二是最近没什么想写的东西.前两天,在预处理图片的时候,发现处理200w张图片,跑了一晚上也才处理 ...

  3. 阿里云系列——6.给你的域名使用CDN加速(详细步骤+简单配置)

    网站部署之~阿里云系列汇总 http://www.cnblogs.com/dunitian/p/4958462.html 进入管理页面:https://home.console.aliyun.com/ ...

  4. Android自定义控件之自定义组合控件

    前言: 前两篇介绍了自定义控件的基础原理Android自定义控件之基本原理(一).自定义属性Android自定义控件之自定义属性(二).今天重点介绍一下如何通过自定义组合控件来提高布局的复用,降低开发 ...

  5. RXJava by Example--转

    原文地址:https://www.infoq.com/articles/rxjava-by-example Key takeaways Reactive programming is a specif ...

  6. 【分布式】Zookeeper的服务器角色

    一.前言 前一篇已经详细的讲解了Zookeeper的Leader选举过程,下面接着学习Zookeeper中服务器的各个角色及其细节. 二.服务器角色 2.1 Leader Leader服务器是Zook ...

  7. [占位-未完成]scikit-learn一般实例之十一:异构数据源的特征联合

    [占位-未完成]scikit-learn一般实例之十一:异构数据源的特征联合 Datasets can often contain components of that require differe ...

  8. domReady的实现

    我们都知道JQ的 $(document).ready(fn) 方法.可以在页面准备就绪后才执行脚本,该方法相比传统的window.onload 事件,它的优势体现于onload事件是需要等到页面中所有 ...

  9. Visual Studio (VSIX,项目模板 )制作

    下载Vsiual Studio 2012 SDK 下载地址:http://www.microsoft.com/en-us/download/details.aspx?id=30668 提示:一定要注意 ...

  10. C#开发微信门户及应用(14)-在微信菜单中采用重定向获取用户数据

    我曾经在系列文章中的<C#开发微信门户及应用(11)--微信菜单的多种表现方式介绍>中介绍了微信菜单里面的重定向操作,通过这个重定向操作,我们可以获取一个code值,然后获取用户的open ...