一个表查询
索引
全表扫描
两个表关联
小表驱动大表
一般引起性能问题的多是复杂的子查询
select 后面的查询 官方叫法就叫标量子查询
select a.owner,a.object_name,(select object_type from test2 where object_id=a.object_id) object_type from test a
作业! 1 . 写一个脚本把标量子查询抓出来,标量自查询需要改成左连接、右连接。 如果不能改成外连接的情况在连接列建立索引,但是建立索引时需要防止回标。
提醒,有标量的是不是depth=1并且 cost大于=2 查看 :V$SQL_PLAN
今天讲where后面的子查询 in not in exists not exists 叫半连接/反连接,很有可能产生filter。
filter 的缺点 ,无法改驱动表。 作为一个dba无法改优化方案那就表示不可控制。 所以尽量避免产生filter。
在生产反正中是否经常遇到
select ... from a, v_b where a.id=v_b.id;
比喻说a 有100条,v_b中有100w,肯定死
但是如果a能传值给v_b这个时候不死。类似谓词推入。关键看有没有传值进去。没传走hash,传进去了走nl。
那怎么判断有没有传值进去,
FROM user_tables a, dba_objects b
WHERE a.TABLE_NAME = b.OBJECT_NAME
AND b.OWNER = 'HBTELEPS'
AND B.OBJECT_TYPE = 'TABLE';
当SQL语句中有内联视图(in-line view,内联视图就是在from后面有select子查询)
或者SQL语句中有用 create view...创建的视图,CBO会将内联视图/视图给展开,进行等价的改写,这个过程就叫做视图合并。如果没有发生视图合并,在执行计划中,我们可以看到VIEW关键字。
其实就是看执行计划里面有没有view关键字。
究竟视图合并会对性能带来什么影响呢?
一个sql语句执行计划有且仅有一个是最优的。
视图合并后执行计划就混乱了,
用一个hint让视图不合并,
SELECT /*+ no_merge(a) */ to_char(wmsys.wm_concat(a.TABLE_NAME))
FROM user_tables a, dba_objects b
WHERE a.TABLE_NAME = b.OBJECT_NAME
AND b.OWNER = 'HBTELEPS'
AND B.OBJECT_TYPE = 'TABLE';
用no_merge 告诉oracle优化器不要对a进行视图合并
这两个视图不合并走hash,hash不传值,视图不合并是不是意味着视图一定会当成一个整体。 当成了整体是不是可以传值进去呢,有些视图可以,有些视图不可以。
那些可以?那些不可以呢?
select /*+ no_merge(a) */ from v_a,v_b,c where v_a=c.id and c.xx=v_b.xx;
v_a 1w
v_b 10w
c 100
我不管你跑多久,我先把你视图单独跑,看你视图是不是产生视图合并。
select /*+ no_merge(v_a) no_merge(v_b) */ from v_a,v_b,c where v_a=c.id and c.xx=v_b.xx;
---------------------------------------------------
select * from v_a,v_b,c where v_a=c.id and c.xx=v_b.xx;
v_a 1w
v_b 10w
c 100
如果v_a单独跑还需要很长时间,那么直接处理v_a视图。
什么样的视图不能被合并呢?
当
1.子查询有 ROWNUM
2.子查询有 CUBE,ROLLUP
3.子查询有 UNION, UNION ALL
4. START WITH ,CONNECT BY (树形查询)
in 和exists等价改写
select ename, deptno
from emp
where deptno in (select deptno
from dept
where dname = 'CHICAGO'
union
select deptno from dept where loc = 'CHICAGO');
-------------------------------------------------------------------------------------------------------------------------------------------
select ename, deptno
from emp
where deptno in (select /*+ unnest */ deptno
from dept
where dname = 'CHICAGO'
union
select deptno from dept where loc = 'CHICAGO');
----------------------------------------------------------------------------------------------------------------------------------------------
select ename, deptno
from emp
where exists (select 1
from dept
where emp.deptno=dept.deptno and dname = 'CHICAGO'
union
select 1from dept where emp.deptno=dept.deptno loc = 'CHICAGO');
-------------------------------------------------------------------------------------------------------------------------------------------
from emp
where exists (select 1 from (select /*+ unnest */ deptno
from dept
where dname = 'CHICAGO'
union
select deptno from dept where loc = 'CHICAGO') a where a.deptno=emp.deptno );
/*+ unnest */ 不产生filter的意思。