一、SQL語句優(yōu)化
(1)SELECT子句中避免使用' * ':ORACLE在解析的過程中,會將' * '依次轉換成所有的列名, 這個工作是通過查詢數據字典完成的,這意味著將耗費更多的時間。
(2)sql語句用大寫的:因為oracle總是先解析sql語句,把小寫的字母轉換成大寫的再執(zhí)行。
(3)使用表的別名(Alias):當在SQL語句中連接多個表時, 請使用表的別名并把別名前綴于每個Column上。這樣一來,就可以減少解析的時間并減少那些由Column歧義引起的語法錯誤。
(4) 用>=替代>:
高效: SELECT * FROM EMP WHERE DEPTNO >=4?
低效: SELECT * FROM EMP WHERE DEPTNO >3?
兩者的區(qū)別在于, 前者DBMS將直接跳到第一個DEPT等于4的記錄而后者將首先定位到DEPTNO=3的記錄并且向前掃描到第一個DEPT大于3的記錄。
(5) 用EXISTS替代IN、用NOT EXISTS替代NOT IN:在許多基于基礎表的查詢中,為了滿足一個條件,往往需要對另一個表進行聯(lián)接.在這種情況下, 使用EXISTS(或NOT EXISTS)通常將提高查詢的效率。 在子查詢中,NOT IN子句將執(zhí)行一個內部的排序和合并。無論在哪種情況下,NOT IN都是最低效的 (因為它對子查詢中的表執(zhí)行了一個全表遍歷)。 為了避免使用NOT IN ,我們可以把它改寫成外連接(Outer Joins)或NOT EXISTS。
例子:
(高效)SELECT * FROM EMP (基礎表) WHERE EMPNO > 0 AND EXISTS (SELECT ‘X' FROM DEPT WHERE DEPT.DEPTNO = EMP.DEPTNO AND LOC = ‘MELB')
(低效)SELECT * FROM EMP (基礎表) WHERE EMPNO > 0 AND DEPTNO IN(SELECT DEPTNO FROM DEPT WHERE LOC = ‘MELB')
(6)用EXISTS替換DISTINCT:例如:
低效: SELECT DISTINCT DEPT_NO,DEPT_NAME FROM DEPT D,EMP E WHERE D.DEPT_NO = E.DEPT_NO
高效: SELECT DEPT_NO,DEPT_NAME FROM DEPT D WHERE EXISTS ( SELECT ‘X’ FROM EMP E WHERE E.DEPT_NO = D.DEPT_NO);
二、優(yōu)化方法
(01)選擇最有效率的表名順序(筆試???
ORACLE的解析器按照從右到左的順序處理FROM子句中的表名,
FROM子句中寫在最后的表將被最先處理,
在FROM子句中包含多個表的情況下,你必須選擇記錄條數最少的表放在最后,
如果有3個以上的表連接查詢,那就需要選擇那個被其他表所引用的表放在最后。
例如:查詢員工的編號,姓名,工資,工資等級,部門名
select emp.empno,emp.ename,emp.sal,salgrade.grade,dept.dname
from salgrade,dept,emp
where (emp.deptno = dept.deptno) and (emp.sal between salgrade.losal and salgrade.hisal)
? ? ? 1)如果三個表是完全無關系的話,將記錄和列名最少的表,寫在最后,然后依次類推
? ? ? 2)如果三個表是有關系的話,將引用最多的表,放在最后,然后依次類推
(02)WHERE子句中的連接順序(筆試常考)
ORACLE采用自右而左的順序解析WHERE子句,根據這個原理,表之間的連接必須寫在其他WHERE條件之左,
那些可以過濾掉最大數量記錄的條件必須寫在WHERE子句的之右。
例如:查詢員工的編號,姓名,工資,部門名
select emp.empno,emp.ename,emp.sal,dept.dname
from emp,dept
where (emp.deptno = dept.deptno) and (emp.sal > 1500)
(03)SELECT子句中避免使用*號
ORACLE在解析的過程中,會將*依次轉換成所有的列名,這個工作是通過查詢數據字典完成的,這意味著將耗費更多的時間
select empno,ename from emp;