ORACLE SQL查询优化

1、优化解析时间

语句缓存  SQL语句 -》共享池 -》高速缓存

软解析:从共享池中 取出 以前的解析 过的语句
硬解析:重新开始新的解析

硬解析会消耗资源多很多,SQL可以复用还是要复用的。

sql语句 -> hsah 值 当做key ,<key,sql>存入高速缓存中(Sql语句的大小写会影响KEY)
使用绑定变量,sql还可以复用

所以,sql查询两次的大小写不要变来变去,还有,使用绑定变量。

select * from v$sql 可以查询出在高速缓存池的sql语句

2、索引查询

在必要列中添加索引。

索引分为 唯一性索引、普通索引、组合索引。

组合索引:
1:适用在单独查询返回记录很多,组合查询后忽然返回记录很少的情况:如以类别和
2:要考虑顺序,第一列为引导列,
oracle索引扫描类型:索引范围扫描、索引唯一扫描、索引全扫描、索引跳跃扫描、索引快速全扫描
索引唯一扫描: 对 unique、primary key索引作为调节的时候,会使用唯一扫描
索引范围扫描:
    返回值不唯一,索引列可以是唯一索引,也可以是不唯一索引,条件可以是 <、>、=等
    范围扫描索引表
索引全扫描:
    1:选择列是唯一性索引,也就是全扫描索引就可以得到值 (id 为索引列)
        比如 select id from tb_xxx
    2:使用max(索引列)
    select max(dabh) from tb_da
索引跳跃扫描
    复合索引中,非引导列查询可能走索引跳跃扫描
索引快速全扫描
    当索引列有非空约束时,这时索引

怎么查询是怎么走索引的呢,对了,执行计划:

方法1:
EXPLAIN PLAN FOR
SELECT * FROM SCOTT.EMP; --要解析的SQL脚本
SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY);

(PL/SQL F5 也能进入此处的执行计划)

不用执行SQL语句就可以进行分析,但信息量少

方法2:sqlplus命令
set autotrace traceonly explain;
select * from ....

通过执行计划,就可以看到到底是全表查询还是索引查询。

你还可以通过执行计划看到TABLE ACCESS BY INDEX ROWID 操作,这个就是回表,回表也有一定的时间消耗

回表:
TABLE ACCESS BY INDEX ROWID
oracle查询的列 不在索引列时,会根据rowid去回表查询

不走索引的情况(SQL优化的重点):
1:name like '%ss%' 会不走索引
2:查询是 索引 列值 ='' 或者 is null,null值不会存在B树里面,所以不会走索引
3:not in 不会走索引,!= 不会走索引
4:当查询的数量值特别多(占有 20% 以上?),直接走全表查询,不走索引。
    像 <、> 要根据返回值的数量来决定走不走索引,oracle 会智能统计信息,来优化执行计划。
5:在包含有null值的table列上建立索引,当时使用select count(*) from table时不会使用索引

 

3、in、or的优化

网上很多说 in 不走索引,其实是错误的,那应该是老版本的数据库,in走不走索引,应该还要看返回列的数量多少,通常in是走索引的。

通常情况下in的效率会比or高

in的优化:
思路1:
sql语句中经常使用in来查询
oracle有个限制,不能超过1000个参数
而且这种用法很低效,可以把参数设为一个表,做hash join查询提高性能

1、用exists来代替(特定情况下)
2:用left join 代替

 

In和exists对比:
若子查询结果集比较小,优先使用in,若外层查询比子查询小,优先使用exists。
因为若用in,则oracle会优先查询子查询,然后匹配外层查询,
若使用exists,则oracle会优先查询外层表,然后再与内层表匹配。最优化
匹配原则,拿最小记录匹配大记录。

 

union all : 两张表进行合并,不去重,不排序,效率比union高很多
union: 两张表进行合并,去重+排序
select id,dabh from tb_a where xxx
union all
select id,dabh from tb_b,where xxx
在不用索引的情况下,用union all代替in的效率会高,具体还需要测试

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章