Oracle 優化
1.SQL語句解析:
從後面往前(從右到左)的解析順序: select id from t1,t2,.......tn tn先解析,解析完tn再解析tn-1,合併tn與tn-1數據,再解析tn-2,所以記錄最少的表應該放到最後,即基表
2.多表查詢,交叉表作爲基表
EMP表描述了LOCATION表和CATEGORY表的交集
a.低效
AND E.EMP_NO BETWEEN 1000 AND 2000
AND E.CAT_NO = C.CAT_NO AND E.LOCN = L.LOCN
a.低效
SELECT * FROM EMP E WHERE SAL > 50000 AND JOB = ‘MANAGER'
AND 25 < (SELECT COUNT(*) FROM EMP WHERE MGR=E.EMPNO);
b.高效
SELECT * FROM EMP E WHERE 25 <(SELECT COUNT(*) FROM EMP WHERE MGR=E.EMPNO);
AND SAL>50000 AND JOB = 'MANAGER';
4 select * from table
* 效率極低,*要轉換成所有的列名,通過數據字典來實現,消耗更多的時間
5 SQL執行
ORACLE在內部執行了許多工作: 解析SQL語句, 估算索引的利用率, 綁定變量 , 讀數據塊等等. 由此可見, 減少訪問數據庫的次數 , 就能實際上減少ORACLE的工作量.
a.低效
SELECT EMP_NAME , SALARY , GRADE FROM EMP WHERE EMP_NO = 342;
SELECT EMP_NAME , SALARY , GRADE FROM EMP WHERE EMP_NO = 291;
b.次低效(使用遊標)
c.高效
SELECT A.EMP_NAME , A.SALARY , A.GRADE, B.EMP_NAME , B.SALARY , B.GRADE FROM EMP A,EMP B WHERE A.EMP_NO = 342 AND B.EMP_NO = 291;
6 HAVING和WHERE GROUP+HAVING < WHERE +GROUP
避免使用HAVING子句, HAVING 只會在檢索出所有記錄之後纔對結果集進行過濾. 這個處理需要排序,總計等操作. 如果能通過WHERE子句限制記錄的數目,那就能減少這方面的開銷
a.低效
SELECT REGION,AVG(LOG_SIZE) FROM LOCATION GROUP BY REGION HAVING REGION REGION != ‘SYDNEY' AND REGION != ‘PERTH'
b.高效
SELECT REGION,AVG(LOG_SIZE) FROM LOCATION WHERE REGION REGION != ‘SYDNEY' AND REGION != ‘PERTH' GROUP BY REGION
7 子查詢的語句,減少對錶的查詢
a.低效
SELECT TAB_NAME FROM TABLES WHERE
TAB_NAME = ( SELECT TAB_NAME FROM TAB_COLUMNS WHERE VERSION = 604)
AND DB_VER= ( SELECT DB_VER FROM TAB_COLUMNS WHERE VERSION = 604)
b.高效
SELECT TAB_NAME FROM TABLES WHERE (TAB_NAME,DB_VER) =
( SELECT TAB_NAME,DB_VER) FROM TAB_COLUMNS WHERE VERSION = 604)
a1.低效
UPDATE EMP SET EMP_CAT = (SELECT MAX(CATEGORY) FROM EMP_CATEGORIES), SAL_RANGE = (SELECT MAX(SAL_RANGE) FROM EMP_CATEGORIES) WHERE EMP_DEPT = 0020;
b1.高效
UPDATE EMP SET (EMP_CAT, SAL_RANGE) = (SELECT MAX(CATEGORY) , MAX(SAL_RANGE) FROM EMP_CATEGORIES) WHERE EMP_DEPT = 0020;
8.SQL鏈接多個表時,儘量用表的別名,減少解析時間及由Column引發的奇異(貌似與2NF衝突)
9 EXITS(NOT EXITS) 高效於IN(NOT IN)
SELECT * FROM EMP (基礎表) WHERE EMPNO > 0 AND DEPTNO IN (SELECT DEPTNO FROM DEPT
WHERE LOC = ‘MELB')
SELECT * FROM EMP (基礎表) WHERE EMPNO > 0 AND EXISTS (SELECT * FROM DEPT WHERE
DEPT.DEPTNO = EMP.DEPTNO AND LOC = ‘MELB')
10 當提交一個包含一對多表信息(比如部門表和僱員表)的查詢時,避免在SELECT子句中使用DISTINCT. 一般可以考慮用EXIST替換
a.低效
SELECT DISTINCT DEPT_NO,DEPT_NAME FROM DEPT D,EMP E WHERE D.DEPT_NO = E.DEPT_NO
b.高效
SELECT DEPT_NO,DEPT_NAME FROM DEPT D WHERE EXISTS ( SELECT * FROM EMP E WHERE E.DEPT_NO = D.DEPT_NO);
EXISTS 使查詢更爲迅速,因爲RDBMS核心模塊將在子查詢的條件一旦滿足後,立刻返回結果.
![endif]-->!--[if>![endif]-->!--[if>