1. procedure 和 function 中的select 后面不要跟变量,否则会极大的影响SQL效率。
2. TRUNCATE 在procedure中无法使用,可写成:
EXECUTE IMMEDIATE 'truncate table smic_rtd_bullet_lot_tmp';
3. 当运行DML(数据操作语言,增删改查)语句时,PL/SQL打开一个内建游标并处理结果,游标是维护查询结果的内存中的一个区域,游标在运行DML语句时打开,完成后关闭。隐式游标只使用SQL%FOUND,SQL%NOTFOUND,SQL%ROWCOUNT三个属性。SQL%FOUND, SQL%NOTFOUND是布尔值,SQL%ROWCOUNT是整数值。结束循环时可以此作为退出循环的判断标准。
4. 为了不重复解析相同的SQL语句,在第一次解析之后,ORACLE将SQL语句存放在内存中。这块位于系统全局区域SGA(system global area)的共享池(shared buffer pool)中的内存可以被所有的数据库用户共享。因此,当你执行一个SQL语句(有时被称为一个游标)时,如果它和之前的执行过的语句完全相同,ORACLE就能很快获得已经被解析的语句以及最好的执行路径。共享的语句必须满足三个条件:
a. 字符级的比较:当前被执行的语句和共享池中的语句必须完全相同。包括所有的空格和字母大小写。
b. 两个语句所指的对象必须完全相同。比如两个用户对于同一个表,一个是table owner,一个是引用同义词,那么是无法SQL共享的。
c. 两个SQL语句中必须使用相同的名字的绑定变量。只要变量名字相同,即使在运行时,赋于不同的绑定变量相同的值也是可以的。
同一SQL在一个session多处使用,如果多次变更,经常因为空格和字母大小写不一致导致SQL没有共享。使用 WITH a AS (SELECT * FROM ……) 将查询命名为a,之后可以将a当做SQL使用,可以确保一次解析多次使用,能够提高效率。
5. 只要有可能,在程序中尽量多使用COMMIT,这样程序的性能得到提高,需求也会因为COMMIT所释放的资源而减少:
COMMIT所释放的资源:
a. 回滚段上用于恢复数据的信息
b. 被程序语句获得的锁
c. redo log buffer 中的空间
d. ORACLE为管理上述3种资源中的内部花费
在使用COMMIT时必须要注意到事务的完整性,现实中效率和事务完整性往往是鱼和熊掌不可得兼。
6. 通过内部函数提高SQL效率。
SELECT H.EMPNO,E.ENAME,H.HIST_TYPE,T.TYPE_DESC,COUNT(*)
FROM HISTORY_TYPE T,EMP E,EMP_HISTORY H
WHERE H.EMPNO = E.EMPNO
AND H.HIST_TYPE = T.HIST_TYPE
GROUP BY H.EMPNO,E.ENAME,H.HIST_TYPE,T.TYPE_DESC;
通过调用下面的函数可以提高效率。
FUNCTION LOOKUP_HIST_TYPE(TYP IN NUMBER) RETURN VARCHAR2
AS
TDESC VARCHAR2(30);
CURSOR C1 IS
SELECT TYPE_DESC
FROM HISTORY_TYPE
WHERE HIST_TYPE = TYP;
BEGIN
OPEN C1;
FETCH C1 INTO TDESC;
CLOSE C1;
RETURN (NVL(TDESC,’?’));
END;
FUNCTION LOOKUP_EMP(EMP IN NUMBER) RETURN VARCHAR2
AS
ENAME VARCHAR2(30);
CURSOR C1 IS
SELECT ENAME
FROM EMP
WHERE EMPNO=EMP;
BEGIN
OPEN C1;
FETCH C1 INTO ENAME;
CLOSE C1;
RETURN (NVL(ENAME,’?’));
END;
SELECT H.EMPNO,LOOKUP_EMP(H.EMPNO),
H.HIST_TYPE,LOOKUP_HIST_TYPE(H.HIST_TYPE),COUNT(*)
FROM EMP_HISTORY H
GROUP BY H.EMPNO , H.HIST_TYPE;
很多人习惯性想用一个SQL写出需要的数据,殊不知复杂的SQL往往牺牲了执行效率。 能够掌握上面的运用函数解决问题的方法在实际工作中是非常有意义的。
7. 通常情况下,用UNION替换WHERE子句中的OR将会起到较好的效果。对索引列使用OR将造成全表扫描。注意,以上规则只针对多个索引列有效。如果有column没有被索引,查询效率可能会因为你没有选择OR而降低。