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的效率会高,具体还需要测试