定位有问题的语句

检查执行计划

检查执行过程中优化器的统计信息

分析相关表的记录数、索引情况

改写SQL语句、调整索引、表分析

有些SQL语句不具备优化的可能,需要优化处理方式

达到最佳执行计划

  1. SELECT
  2. temp.*
  3. FROM
  4. (
  5. SELECT
  6. t.MODULE 进程,
  7. t.PARSING_SCHEMA_NAME 用户,
  8. t.EXECUTIONS 执行次数,
  9. trunc ( t.CPU_TIME / 1000 / 1000 / t.EXECUTIONS, 5 ) 平均时间,
  10. t.OPTIMIZER_MODE 优化方式,
  11. t.SQL_TEXT SQL语句,
  12. t.CPU_TIME / 1000 / 1000 CPU_TIME,
  13. t.DISK_READS 读盘次数,
  14. decode( t.COMMAND_TYPE, 3, 'select', 2, 'insert', 6, 'update', 7, 'delete', 'plsql' ) 命令类型,
  15. t.SQL_FULLTEXT 完整 SQL,
  16. t.SHARABLE_MEM 占用 sharedpool内存,
  17. t.BUFFER_GETS 读取缓冲区的次数
  18. FROM
  19. V$SQLAREA t
  20. WHERE
  21. t.EXECUTIONS > 0
  22. AND t.PARSING_USER_ID NOT IN ( 0, 51 )) temp
  23. ORDER BY
  24. temp.平均时间 DESC,
  25. temp.执行次数 DESC

  1. 举例:
  2. 低效:
  3.    SELECT ACCT_NUM, BALANCE_AMT
  4. FROM DEBIT_TRANSACTIONS WHERE TRAN_DATE = 31-DEC-95
  5. UNION
  6. SELECT ACCT_NUM, BALANCE_AMT
  7. FROM DEBIT_TRANSACTIONS WHERE TRAN_DATE = 31-DEC-95
  8. 高效:
  9. SELECT ACCT_NUM, BALANCE_AMT
  10. FROM DEBIT_TRANSACTIONS WHERE TRAN_DATE = 31-DEC-95
  11. UNION ALL
  12. SELECT ACCT_NUM, BALANCE_AMT
  13. FROM DEBIT_TRANSACTIONS WHERE TRAN_DATE = 31-DEC-95

①存在数据类型隐形转换

②列上有数学运算

③使用不等于(<>)运算

④使用substr字符串函数

⑤‘%’通配符在第一个字符

在很多情况下可能无法避免这种情况:

  1. SELECT t.jjdbh, T.JJYXM, T.JJYGH FROM JJDB t WHERE T.JJDBH like '%2013%'

但是一定要心中有底,通配符如此使用会降低查询速度。然而当通配符出现在字符串其他位置时,优化器就能利用索引。

在下面的查询中索引得到了使用:

  1. SELECT t.jjdbh, T.JJYXM, T.JJYGH FROM JJDB t WHERE T.JJDBH like '2013%'

⑥字符串连接(||)

如果表中有两个以上(包括两个)索引,其中有一个唯一性索引,而其他是非唯一性.

在这种情况下,ORACLE将使用唯一性索引而完全忽略非唯一性索引.

举例:

  1. SELECT t.jjdbh,T.JJYXM,T.JJYGH FROM JJDB t
  2. WHERE T.GXDWDM = 330105510000 AND T.JJDBH = ''

如果索引是建立在多个列上, 只有在它的第一个列被where子句引用时,优化器才会选择使用该索引

  1. SELECTt.jjdbh,T.JJYXM,T.JJYGH FROM JJDB t WHERE T.HRSJ > sysdate -1

  1. SELECTt.jjdbh,T.JJYXM,T.JJYGH FROM JJDB t WHERE T.JJLXDM =1

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

  1. SELECT t.JJDBH,T.JJYXM,T.JJYGH FROM JJDB t WHERE T.JJDBH || '' = '';

  1. SELECT t.JJDBH,T.JJYXM,T.JJYGH FROM JJDB t WHERE T.JJDBH =substr( '',0,16);

WHERE子句中, 如果索引列所对应的值的第一个字符由通配符开始, 索引将不被采用.

  1. SELECT t.jjdbh,T.JJYXM,T.JJYGH FROM JJDB t WHERE T.JJDBH LIKE '%1387221538518234';

  1. SELECT t.JJDBH, T.JJYXM, T.JJYGH FROM JJDB t WHERE T.JJDBH LIKE '1387221538518234%';

任何在 WHERE子句中使用IS NULL或IS NOT NULL的语句优化器是不允许使用索引的

  1. SELECT t.jjdbh, T.JJYXM, T.JJYGH FROM JJDB t WHERE T.HRSJ IS NOT NULL
  2. SELECT t.jjdbh, T.JJYXM, T.JJYGH FROM JJDB t WHERE T.HRSJ IS NULL

避免出现索引列自动转换

当比较不同数据类型的数据时, ORACLE自动对列进行简单的类型转换.因为内部发生的类型转换, 这个索引将不会被用到!

  1. SELECT t.JJDBH, T.JJYXM, T.JJYGH FROM JJDB t WHERE T.JJDBH = '66666666‘
  1. SELECT t.jjdbh, T.JJYXM, T.JJYGH FROM JJDB t WHERE T.JJDBH = 66666666

减少访问数据库的次数

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

由此可见, 减少访问数据库的次数 , 就能实际上减少ORACLE的工作量

使用DECODE来减少处理时间

  1. SELECT COUNT (*), SUM (t.jjsc) FROM JJDB t
  2. WHERE T.HRSJ > TO_DATE ('2013-7-26', 'yyyy-mm-dd')
  3. AND T.HRSJ < TO_DATE ('2013-7-29', 'yyyy-mm-dd') AND T.BJLBDM = 10;
  4.  
  5. SELECT COUNT (*), SUM (t.jjsc) FROM JJDB t
  6. WHERE T.HRSJ > TO_DATE ('2013-7-26', 'yyyy-mm-dd')
  7. AND T.HRSJ < TO_DATE ('2013-7-29', 'yyyy-mm-dd') AND T.BJLBDM = 99;
  8.  
  9. SELECT COUNT (DECODE (t.BJLBDM, 10, 1, NULL)) count_lb10,
  10. COUNT (DECODE (t.BJLBDM, 99, 1, NULL)) count_lb99,
  11. SUM (DECODE (t.BJLBDM, 10, t.jjsc, NULL)) sum_lb10,
  12. SUM (DECODE (t.BJLBDM, 99, t.jjsc, NULL)) sum_lb99
  13. FROM JJDB t
  14. WHERE T.HRSJ > TO_DATE ('2013-7-26', 'yyyy-mm-dd') AND T.HRSJ < TO_DATE ('2013-7-29', 'yyyy-mm-dd')

减少对表的查询

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

  1. SELECT t.jjdbh, T.JJYXM, T.JJYGH
  2. FROM JJDB t
  3. WHERE T.JJYXM = (SELECT xm FROM jjyb WHERE bh = 307)
  4. AND T.JJYGH = (SELECT jjyjh FROM jjyb WHERE bh = 307);

  1. SELECT t.jjdbh, T.JJYXM, T.JJYGH
  2. FROM JJDB t
  3. WHERE (T.JJYXM, T.JJYGH) = (SELECT xm, jjyjh FROM jjyb WHERE bh = 307)

组合索引

由多个列构成的索引,如create index IDX_JJDB1 on JJDB (HRSJ, JJDM, BSDM, JJYGH) ,

则我们称IDX_JJDB1索引为组合索引。在组合索引中有一个重要的概念:引导列,在上面的例子中, HRSJ列为引导列。

当我们进行查询时可以使用”where HRSJ = ? ”,也可以使用”where HRSJ = ? and JJDM= ?”,这样的限制条件都会使用索引,

但是”where BSDM= ? ”查询就不会使用该索引。

所以限制条件中包含先导列时,该限制条件才会使用该组合索引。

常用Sql _ 查看表空间

  1. SELECT
  2. b.file_name 物理文件名,
  3. b.tablespace_name 表空间,
  4. b.bytes / 1024 / 1024 大小 M,
  5. (
  6. b.bytes - sum(
  7. nvl ( a.bytes, 0 ))) / 1024 / 1024 已使用 M,
  8. substr(( b.bytes - sum( nvl ( a.bytes, 0 ))) / ( b.bytes ) * 100, 1, 5 ) 利用率
  9. FROM
  10. dba_free_space a,
  11. dba_data_files b
  12. WHERE
  13. a.file_id = b.file_id
  14. GROUP BY
  15. b.tablespace_name,
  16. b.file_name,
  17. b.bytes
  18. ORDER BY
  19. b.tablespace_name;

更改表空间大小

  1. ALTER DATABASE datafile '/ora/oradata/radius/undo.dbf' resize 10240m

常用Sql _ 查看当前连接会话

  1. SELECT * FROM v$ SESSION WHERE username IS NOT NULL;
  2. SELECT username, count( username ) FROM v$ SESSION
  3. WHERE username IS NOT NULL GROUP BY username;

常用 SQL _ 表锁相关
1.查看被锁的表 SELECT

  1. SELECT p.spid,a.serial#,c.object_name, b.session_id, b.oracle_username,b.os_user_name
  2. FROM v$process p, v$ SESSION a, v$locked_object b, all_objects c
  3. WHERE p.addr = a.paddr AND a.process = b.process AND c.object_id = b.object_id

2.查看是哪个进程锁的

  1. SELECT sid,serial#, username, osuser FROM v$session where osuser = 'dsdb'

3.杀掉这个进程

  1. ALTER system KILL SESSION 'sid,serial#';

如果表中的时间字段是索引,那么时间字段不要使用函数,函数会使索引失效。

例如:

  1. select * from mytable where trunc(createtime)=trunc(sysdate);
    --不走索引,慢吞吞。createtime字段有时分秒,使用trunc()函数去除时分秒,只保留年月日

改进方案:

  1. select * from mytable where createtime between to_date(to_char(trunc(SYSDATE), 'yyyy/mm/dd hh24:mi:ss'),
  2. 'yyyy/mm/dd hh24:mi:ss') and to_date(to_char(trunc(SYSDATE), 'yyyy/mm/dd hh24:mi:ss'), 'yyyy/mm/dd hh24:mi:ss');
    --走索引,效率飞升

避免使用 *

当你想在SELECT子句中列出所有的列时,使用动态 SQL列引用 ‘*’ 是一个方便的方法.这是一个非常低 效的方法. 实际上,

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

ORACLE在解析sql语句的时候对FROM子句后面的表名是从右往左解析的,是先扫描最右边的表,然后在扫描左边的表,然后用左边的表匹配数据,匹配成功后就合并。

所以,在对多表查询中,一定要把小表写在最右边,如果有中间表,中间表写在最右边,然后是最小表。

ORACLE采用自下而上、从右向左的顺序解析WHERE子句,可以过滤掉最大数量记录的条件必须写在WHERE子句的末尾。

影响查询速度的条件写在WHERE子句的最前面。像索引查询速度快的就放在where条件的末尾。

在含有子查询的SQL语句中,不要同一个表查询多次。

通常来说 ,采用表连接的方式比EXISTS更有效率 。

最终结果如何,请参考实际测试的运行时间

具体参考:https://www.cnblogs.com/zjfjava/p/7092503.html

oracle查询SQL优化相当重要的更多相关文章

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

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

  2. 基于oracle的sql优化

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

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

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

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

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

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

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

  6. Oracle之SQL优化专题03-如何看懂SQL的执行计划

    专题第一篇<Oracle之SQL优化专题01-查看SQL执行计划的方法>讲到了查看SQL执行计划的方法,并介绍了各种方法的应用场景,那么这一篇就主要介绍下如何看懂SQL的执行计划.毕竟如果 ...

  7. ORACLE常用SQL优化hint语句

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

  8. Oracle数据库SQL优化

    SQL优化的最终目的是用户体验-在最短时间内让用户在页面数据.因此,执行时间是SQL优化的重要指标.在SQL查询中,I/O操作最占系统性能的.I/O操作量越大,时间越久.减少I/O操作量是优化SQL的 ...

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

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

随机推荐

  1. super与this无法用在static方法中

    更新记录 [1]2020.02.08-10:32 1.主要编辑了super 正文 我原本是在学习\(super\)关键字,后来突发奇想,能不能在父类中用\(super\)间接调用本类方法呢? 也就是说 ...

  2. hbase meta中分区信息错误的记录

    bulk write hbase 时遇到下面的错误: 19/03/20 02:16:02 ERROR LoadIncrementalHFiles: IOException during splitti ...

  3. 吴裕雄 Bootstrap 前端框架开发——Bootstrap 辅助类:表格单元格使用了 "bg-danger" 类

    <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ...

  4. Python学习第六课——基本数据类型一之tuple and dict

    元组 (tuple) tu=(11,22,(123,456),[22,55],) # 一般定义元组的时候最后面加一个, # 元组不能被修改或者删除 v = tu[0] # 也可以根据索引取值 prin ...

  5. 可以看一下我学习linux的过程

    学习Linux的最佳方法是将它用于日常工作. 阅读Linux书籍,观看Linux视频不仅仅是足够的. 学习Linux没有捷径可走. 你不可能在一夜之间在Linux中掌握. 这需要时间和持久性. 刚刚潜 ...

  6. Memcached 最新版本发布,不再仅仅是个内存缓存了

    导读 Memcached 1.5.18和之后版本可以在服务重启时恢复内存缓存.新版本还通过DAX文件系统挂载来实现缓存持久性功能. 可以通过在启动选项使用该功能: -e /tmpfs_mount/me ...

  7. 多线程分析之Semaphore

    Semaphore分析由来 网上看了许多讲解Semaphore的,用Semaphore来实现顺序打印字母,但是可能大家都没有清楚具体的原因,所以来给大家分析下为什么可以使用Semaphore来实现顺序 ...

  8. 解决css中display:inline-block的兼容问题

    *display:inline; *zoom:1; 不多说,ie6/7直接在元素添加以上的属性即可.

  9. 「AT1983 BBQ Hard」

    呦,来一次久违的BBQ吧! AT题...日本的题库质量一向很高 这题是有关组合数的DP... 前置芝士 快速计算组合数,具体还是自行百度. 膜域下的除法. 具体做法 题目中的问题: \(\sum_{i ...

  10. Day1-D-CF-1144C

    简述:给你一个数组,判断是否能拆分成2个数组,一个递增一个递减,若不行输出No,可以就Yes并分别输出 思路:统计每个数出现的次数,若有大于2的肯定无法组成严格单调,这样就只需要将出现两次的组成递,剩 ...