-------------------------
0 SELECT STATEMENT Optimizer=RULE
1 0 SORT (GROUP BY)
2 1 FILTER
3 2 TABLE ACCESS (FULL) OF 'CBQ_LCH_USAGE0'
4 2 TABLE ACCESS (FULL) OF 'CBQ_QF_USAGE1'
Elapsed: 13:48:26.85
调整:
not in 改成not exists
create index idx_serviceorderid on cbq_qf_usage1(serviceorderid) nologging;
select 'XJ'||1||'180','停机保号用户数',count(distinct serviceid),1,'200509',a.groupid
from cbq_lch_usage0 a
where a.subsidiaryid=1 and a.subid<>'02' and a.subid<>'06' and a.status='7'
and not exists(select 1 from cbq_qf_usage1 b where status<>'3' and status<>'8' and a.serviceid=b.serviceorderid)
group by 'XJ'||1||'180','停机保号用户数',1,'200509',a.groupid;
Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=RULE
1 0 SORT (GROUP BY)
2 1 FILTER
3 2 TABLE ACCESS (FULL) OF 'CBQ_LCH_USAGE0'
4 2 TABLE ACCESS (BY INDEX) OF 'CBQ_QF_USAGE1'
5 4 INDEX (RANGE SCAN) OF 'IDX_SERVICEORDERID'
Elapsed: 00:00:01.36
九.其他
1.SELECT子句中避免使用 ‘ * ‘
当你想在SELECT子句中列出所有的COLUMN时,使用动态 SQL列引用 ‘*’ 是一个方便的方法.不幸的是,这是一个非常低效的方法. 实际上,ORACLE在解析的过程中, 会将’*’ 依次转换成所有的列名, 这个工作是通过查询数据字典完成的, 这意味着将耗费更多的时间.
2.用TRUNCATE替代DELETE
3.使用表的别名(Alias)
当在SQL语句中连接多个表时, 请使用表的别名并把别名前缀于每个Column上.这样一来,就可以减少解析的时间并减少那些由Column歧义引起的语法错误.
4.索引的等级
一般情况索引等级如下:
a) 等式比较比范围比较要高。
b) 唯一性索引比非唯一性索引要高。
c) 一般情况下单列索引等级要比复合索引高,但如果where子句中包含所 有复合索引的字段,则复合索引等级高。
例如:
SELECT col1, ...
FROM emp
WHERE emp_name = 'GURRY'
AND emp_no = 127
AND dept_no = 12
Index1 (emp_name)
Index2 (emp_no, dept_no, emp_name)
ORACLE将使用索引Index2。
5.统计信息分析
在现实当中,有关analyze分析有以下两种误区:
a) 只要对主要的或者关键的表格做分析即可。其实正确的应该是需要对所有涉及到的表格都做过分析。
b) 做一次分析后即可高枕无忧。事实上,一旦做过分析后,就应该定期更新这些统计信息,以保证统计信息的正确性。
6.Exists总比In快
有许多人认为用Exists总比用In要快,这也是一个误区。有时用in反而比用Exists快。
他们之间的区别如下:
IN subquery,首先执行subquery,由subquery来驱动父查询。而Exists子查询则由父查询来驱动子查询。这就是两者之间的区别。
所以如果子查询小的话,则可以采用in会快一些,如果子查询大的话,则采用exists会快一些。
7.>与>=
大于或小于操作符一般情况下是不用调整的,因为它有索引就会采用索引查找,但有的情况下可以对它进行优化,如一个表有100万记录,一个数值型字段A,
30万记录的A=0,30万记录的A=1,39万记录的A=2,1万记录的A=3。
那么执行A>2与A>=3的效果就有很大的区别了,因为A>2时ORACLE会先找出
为2的记录索引再进行比较,而A>=3时ORACLE则直接找到=3的记录索引。
8. 使用索引来避免排序
索引是排好序的,在某些情况下可以使用索引来避免排序。
SELECT acc_name, acc_surname
FROM account acct
ORDER BY 1;
SELECT /*+ INDEX_ASC(acct acc_ndx1) */ acc_name,acc_surname
FROM account acct;
9.大对象操作
a)Big Insert
(1)direct insert(serial and parallel)
insert /*+append*/into tab1 select * from tab2;
Insert /*+append parallel(emp,8)*/ into emp select * from emp_bak;
(2)nologging
insert into tab1 nologging select * from tab2;
(3)Large extent size
更大的extent可以获得更好的insert性能。
(5)Large rollback segment
b)Large Index Create
大的索引extent size值
大的Sort_area_size值
采用nologging
采用parallel
大的临时表空间
alter session sort_area_size=100000000;
create index xxx on aa(ab) nologging parallel 2;
c)Large Delete
分几次delete。
附录一
Hint全集
174. /*+ALL_ROWS*/
表明对语句块选择基于开销的优化方法,并获得最佳吞吐量,使资源消耗最小化.例如:
SELECT /*+ALL+_ROWS*/ EMP_NO,EMP_NAM,DAT_IN FROM BSEMPMS WHERE EMP_NO='CCBZZP';
175. /*+FIRST_ROWS*/
表明对语句块选择基于开销的优化方法,并获得最佳响应时间,使资源消耗最小化.例如:
SELECT /*+FIRST_ROWS*/ EMP_NO,EMP_NAM,DAT_IN FROM BSEMPMS WHERE EMP_NO='CCBZZP';
176. /*+CHOOSE*/
表明如果数据字典中有访问表的统计信息,将基于开销的优化方法,并获得最佳的吞吐量;表明如果数据字典中没有访问表的统计信息,将基于规则开销的优化方法;例如:
SELECT /*+CHOOSE*/ EMP_NO,EMP_NAM,DAT_