(4).索引列上>=代替>
低效:select * from emp where deptno > 3
高效:select * from emp where deptno >=4
两者的区别在于,前者dbms将直接跳到第一个deptno等于4的记录,而后者将首先定位到deptno等于3的记录并且向前扫描到第一个deptno大于3的。
(5).非要对一个使用函数的列启用索引,基于函数的索引是一个较好的方案。
2. 游标的使用:
当在海量的数据表中进行数据的删除、更新、插入操作时,用游标处理的效率是最慢的,但是游标又是必不可少的,所以正确使用游标十分重要:
(1). 在数据抽取的源表中使用时间戳,这样每天的维表数据维护只针对更新日期为最新时间的数据来进行,大大减少需要维护的数据记录数。
(2). 在insert和update维表时都加上一个条件来过滤维表中已经存在的记录,例如:
insert into dim_customer select * from ods_customer where ods_customer.code not exists (dim_customer.code)
ods_customer为数据源表。dim_customer为维表。
(3). 使用显式的游标,因为隐式的游标将会执行两次操作,第一次检索记录,第二次检查too many rows这个exception,而显式游标不执行第二次操作。
3. 据抽取和上载时的sql优化:
(1). Where 子句中的连接顺序:
oracle采用自下而上的顺序解析where子句,根据这个原理,表之间的连接必须写在其他where条件之前,那些可以过滤掉大量记录的条件必须写在where子句的末尾。如:
低效:select * from emp e where sal>5000 and job = ‘manager’ and 25<(select count (*) from emp where mgr=e.empno);
高效:select * from emp e where 25<(select count(*) from emp where mgr=e.empno) and sal>5000 and job=’manager’;
(2). 删除全表时,用truncate 替代 delete,同时注意truncate只能在删除全表时适用,因为truncate是ddl而不是dml。
(3). 尽量多使用commit
只要有可能就在程序中对每个delete,insert,update操作尽量多使用commit,这样系统性能会因为commit所释放的资源而大大提高。
(4). 用exists替代in ,可以提高查询的效率。
(5). 用not exists 替代 not in
(6). 优化group by
提高group by语句的效率,可以将不需要的记录在group by之前过滤掉。如:
低效:select job, avg(sal) from emp group by job having job = ‘president’ or job=’manager’;
高效: select job, avg(sal) from emp having job=’president’ or job=’manager’ group by job;
(7). 有条件的使用union-all 替代 union:这样做排序就不必要了,效率会提高3到5倍。
(8). 分离表和索引
总是将你的表和索引建立在不同的表空间内,决不要将不属于oracle内部系统的对象存放到system表空间内。同时确保数据表空间和索引表空间置于不同的硬盘控制卡控制的硬盘上。
---与SQL优化(包括内存空间)有关一些INIT参数
OPTIMIZER_MODE
SORT_AREA
SHARED_POOL_SZIE
---一些不使用索引的情况
1,NOT IN
2,NOT BETWEEN
3,LIKE(第一个字符非%号除外,如name like 李%)
4,<>
5,IS NULL/IS NOT NULL
6,查询的字段加函数
7,在8I中,多字段的组合索引(A,B,C),select * from ** wher B=33,则索引也不会用。(按前缀式规则使用索引除外,如A=33 and B=33 || A=33 || A=33 and C=33)
注:9I除外
---查询语句比较优化的写法:
1,加HINT,改变其执行路径
2,可能使用exsit的地方就尽量不用IN,可以使用not exiist的地方,尽量不要用not in
3,两个表进行JION时,大表放在前面,JION字段建索引
4,尽量用其它写法,取代NOT IN,如a,b表同结构,数据量很大,则代替select * from a where a.c not in (select c from b )
的语句有
a)select a.* from a, b where a.c = b.c + and b.c is null(据说速度比原写法提高30倍)
b)select * from a minus select a.* from a,b where a.c=b.c (速度其次)
c)select * from a where not exist(select a.* from a,b where a.c=b.c) (也不错)
---根据Tom的经验,count(*) 和count某列在Oracle8以上没有区别
根据我以前的经验,在有主键,数据量为100000左右的表中使用COUNT(*)比COUNT(主键)要那么快一点点,大概5秒左右。
----like不是都不能使用索引
有一种情况可以使用,在NAME上建索引,使用name like 李%可以用到索引,即LIKE的值中%不要放在最前面
----字段加函数可以考虑使用Function Based Index来代替普通索引
这个我听说过,但不知道哪里有中文文档,我想速成。还有,如果这个函数是我自定义的,且比较复杂,包括了从多个表中的计算。Function Based Index是否还有效。
--请指出动态SQL的dbms_sql和execute immediate的区别的来源?或者以自己实例证明。没有见过这样的说法。谢谢
我会在后面贴上文档,其实dbms_sql与execute immediate各有优点,关键看你的SQL语句的目标。
---两表进行Join,应该是小的表放在前面效率更加好一点?
这也是我的经验,一大,一小两个表,在SELECT中好像表的顺序没有太多影响,但JION条件中,大表放在前面有优势。
如:select big.*,smal.* from big smal where big.col=smal.col
据我的试验PLAN,在JION的两个表中,ORACLE只能用到一边表的索引(一般是前面的表,如BIG),而SMAL则进行全表扫描,所以将大表放在前有好处。
――附,两种动态SQL的区别:
Advantages of Native Dynamic SQL
Native dynamic SQL provides the following advantages over the DBMS_SQL package:
Ease of Use
Native dynamic SQL is much simpler to use than the DBMS_SQL package. Because native dynamic SQL is integrated with SQL, you can use it in the same way that you currently use static SQL within PL/SQL code. In addition, native dynamic SQL co