Oracle 語(yǔ)句優(yōu)化分析說(shuō)明第1/2頁(yè)
例如:
表 TAB1 16,384 條記錄
表 TAB2 1 條記錄
選擇 TAB2作為基礎(chǔ)表 (最好的方法)
select count(*) from tab1,tab2 執(zhí)行時(shí)間 0.96秒
選擇 TAB2作為基礎(chǔ)表 (不佳的方法)
select count(*) from tab2,tab1 執(zhí)行時(shí)間 26.09秒
2. ORACLE 采用自下而上的順序解析 WHERE 子句,根據(jù)這個(gè)原理,表之間的連接必須寫(xiě)在其他 WHERE 條件之前, 那些可以過(guò)濾掉最大數(shù)量記錄的條件必須寫(xiě)在 WHERE 子句的末尾。
例如:
(低效,執(zhí)行時(shí)間 156.3秒)
SELECT …
FROM EMP E
WHERE SAL > 50000
AND JOB = ‘MANAGER'
AND 25 < (SELECT COUNT(*) FROM EMP
WHERE MGR=E.EMPNO);
(高效,執(zhí)行時(shí)間 10.6秒)
SELECT …
FROM EMP E
WHERE 25 < (SELECT COUNT(*) FROM EMP
WHERE MGR=E.EMPNO)
AND SAL > 50000
AND JOB = ‘MANAGER';
3. SELECT子句中避免使用'*'
當(dāng)你想在 SELECT子句中列出所有的 COLUMN時(shí),使用動(dòng)態(tài) SQL列引用 ‘*' 是一個(gè)方便的方法。不幸的是,這是一個(gè)非常低效的方法。 實(shí)際上,ORACLE 在解析的過(guò)程中,會(huì)將‘*' 依次轉(zhuǎn)換成所有的列名, 這個(gè)工作是通過(guò)查詢(xún)數(shù)據(jù)字典完成的, 這意味著將耗費(fèi)更多的時(shí)間。
4. 使用DECODE 函數(shù)來(lái)減少處理時(shí)間, 使用 DECODE 函數(shù)可以避免重復(fù)掃描相同記錄或重復(fù)連接相同的表。
5. 刪除重復(fù)記錄
最高效的刪除重復(fù)記錄方法 ( 因?yàn)槭褂昧?ROWID)
DELETE FROM EMP E
WHERE E.ROWID > (SELECT MIN(X.ROWID)
FROM EMP X
WHERE X.EMP_NO = E.EMP_NO);
6. 計(jì)算記錄條數(shù)
和一般的觀(guān)點(diǎn)相反,count(*) 比 count(1)稍快,當(dāng)然如果可以通過(guò)索引檢索,對(duì)索
引列的計(jì)數(shù)仍舊是最快的。 例如 COUNT(EMPNO)
7. 用WHERE子句替換HAVING子句
避免使用 HAVING子句,HAVING 只會(huì)在檢索出所有記錄之后才對(duì)結(jié)果集進(jìn)行過(guò)濾。
這個(gè)處理需要排序,總計(jì)等操作。 如果能通過(guò) WHERE 子句限制記錄的數(shù)目,那就能減少這方面的開(kāi)銷(xiāo)。
例如:
低效
SELECT REGION,AVG(LOG_SIZE)
FROM LOCATION
GROUP BY REGION
HAVING REGION REGION != ‘SYDNEY'
AND REGION != ‘PERTH'
高效
SELECT REGION,AVG(LOG_SIZE)
FROM LOCATION
WHERE REGION REGION != ‘SYDNEY'
AND REGION != ‘PERTH'
GROUP BY REGION
HAVING 中的條件一般用于對(duì)一些集合函數(shù)的比較,如 COUNT() 等等。除此而外,一般的條件應(yīng)該寫(xiě)在 WHERE 子句中。
8. 減少對(duì)表的查詢(xún)
在含有子查詢(xún)的 SQL語(yǔ)句中,要特別注意減少對(duì)表的查詢(xún)。
例如:
低效
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)
高效
SELECT TAB_NAME
FROM TABLES
WHERE (TAB_NAME,DB_VER)
= ( SELECT TAB_NAME,DB_VER)
FROM TAB_COLUMNS
WHERE VERSION = 604)
9. 使用表的別名ALIAS
當(dāng)在 SQL語(yǔ)句中連接多個(gè)表時(shí), 請(qǐng)使用表的別名并把別名前綴于每個(gè) Column上。這
樣一來(lái),就可以減少解析的時(shí)間并減少那些由 Column歧義引起的語(yǔ)法錯(cuò)誤。
(Column歧義指的是由于 SQL中不同的表具有相同的 Column名,當(dāng) SQL語(yǔ)句中出現(xiàn)這個(gè) Column時(shí),SQL解析器無(wú)法判斷這個(gè) Column的歸屬)
10. 用EXISTS替代IN
在許多基于基礎(chǔ)表的查詢(xún)中,為了滿(mǎn)足一個(gè)條件,往往需要對(duì)另一個(gè)表進(jìn)行聯(lián)接。在這
種情況下, 使用 EXISTS(或 NOT EXISTS)通常將提高查詢(xún)的效率。
低效:
SELECT *
FROM EMP (基礎(chǔ)表)
WHERE EMPNO > 0
AND DEPTNO IN (SELECT DEPTNO
FROM DEPT
WHERE LOC = ‘MELB')
高效:
SELECT *
FROM EMP (基礎(chǔ)表)
WHERE EMPNO > 0
AND EXISTS (SELECT ‘X'
FROM DEPT
WHERE DEPT.DEPTNO = EMP.DEPTNO
AND LOC = ‘MELB')
11. 用NOT EXISTS替代 NOT IN
在子查詢(xún)中, NOT IN子句將執(zhí)行一個(gè)內(nèi)部的排序和合并。 無(wú)論在哪種情況下, NOT IN都是最低效的 (因?yàn)樗鼘?duì)子查詢(xún)中的表執(zhí)行了一個(gè)全表遍歷)。 為了避免使用 NOT IN ,我們可以把它改寫(xiě)成外連接(Outer Joins)或 NOT EXISTS.
例如:
SELECT …
FROM EMP
WHERE DEPT_NO NOT IN (SELECT DEPT_NO
FROM DEPT
WHERE DEPT_CAT='A');
為了提高效率。改寫(xiě)為:
(方法一: 高效)
SELECT ….
FROM EMP A,DEPT B
WHERE A.DEPT_NO = B.DEPT(+)
AND B.DEPT_NO IS NULL
AND B.DEPT_CAT(+) = ‘A'
(方法二: 最高效)
SELECT ….
FROM EMP E
WHERE NOT EXISTS (SELECT ‘X'
FROM DEPT D
WHERE D.DEPT_NO = E.DEPT_NO
AND DEPT_CAT = ‘A');
12. 用表連接替換EXISTS
通常來(lái)說(shuō) ,采用表連接的方式比 EXISTS 更有效率
SELECT ENAME
FROM EMP E
WHERE EXISTS (SELECT ‘X'
FROM DEPT
WHERE DEPT_NO = E.DEPT_NO
AND DEPT_CAT = ‘A');
(更高效)
SELECT ENAME
FROM DEPT D,EMP E
WHERE E.DEPT_NO = D.DEPT_NO
AND DEPT_CAT = ‘A' ;
13. 用EXISTS替換DISTINCT
當(dāng)提交一個(gè)包含一對(duì)多表信息(比如部門(mén)表和雇員表)的查詢(xún)時(shí),避免在 SELECT 子句
中使用 DISTINCT. 一般可以考慮用 EXIST 替換
例如:
低效:
SELECT DISTINCT DEPT_NO,DEPT_N
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);
14. 避免在索引列上使用計(jì)算
WHERE 子句中,如果索引列是函數(shù)的一部分。優(yōu)化器將不使用索引而使用全表掃描。
舉例:
低效:
SELECT …
FROM DEPT
WHERE SAL * 12 > 25000;
高效:
SELECT …
FROM DEPT
WHERE SAL > 25000/12;
:這是一個(gè)非常實(shí)用的規(guī)則,請(qǐng)務(wù)必牢記
相關(guān)文章
Oracle SQL Developer腳本輸出中文顯示亂碼的解決方法
我們?cè)跍y(cè)試Oracle Select AI(自然語(yǔ)言查詢(xún)數(shù)據(jù)庫(kù))時(shí),發(fā)現(xiàn)Run Statement中文顯示正常,而Run Script中文顯示亂碼,所以本文給大家介紹了Oracle SQL Developer腳本輸出中文顯示亂碼的解決方法,需要的朋友可以參考下2024-05-05
Oracle實(shí)現(xiàn)豎表轉(zhuǎn)橫表的幾種常用方法小結(jié)
本文主要介紹了Oracle實(shí)現(xiàn)豎表轉(zhuǎn)橫表的幾種常用方法小結(jié),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2023-04-04
Oracle如何獲取數(shù)據(jù)庫(kù)系統(tǒng)的當(dāng)前時(shí)間
這篇文章主要介紹了Oracle如何獲取數(shù)據(jù)庫(kù)系統(tǒng)的當(dāng)前時(shí)間問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-12-12
Oracle 高速批量數(shù)據(jù)加載工具sql*loader使用說(shuō)明
SQL*Loader(SQLLDR)是Oracle的高速批量數(shù)據(jù)加載工具,這是一個(gè)非常有用的工具,可用于多種平面文件格式向Oralce數(shù)據(jù)庫(kù)中加載數(shù)據(jù)2012-12-12
Oracle minus用法詳解及應(yīng)用實(shí)例
這篇文章主要介紹了Oracle minus用法詳解及應(yīng)用實(shí)例的相關(guān)資料,這里對(duì)oracle minus的用法進(jìn)行了具體實(shí)例詳解,需要的朋友可以參考下2017-01-01
Oracle 12CR2查詢(xún)轉(zhuǎn)換教程之表擴(kuò)展詳解
Oracle 12cR2版本已經(jīng)發(fā)布有一段時(shí)間,下面這篇文章主要給大家介紹了關(guān)于Oracle 12CR2查詢(xún)轉(zhuǎn)換教程之表擴(kuò)展的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友可以參考借鑒,下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2018-11-11
ORACLE應(yīng)用經(jīng)驗(yàn)(1)
ORACLE應(yīng)用經(jīng)驗(yàn)(1)...2007-03-03
數(shù)據(jù)庫(kù)ORA-01196故障-歸檔日志丟失恢復(fù)詳解
這篇文章主要介紹了數(shù)據(jù)庫(kù)ORA-01196故障-歸檔日志丟失恢復(fù)詳解,具有一定參考價(jià)值,需要的朋友可以了解下。2017-10-10
Oracle?range時(shí)間范圍自動(dòng)分區(qū)的創(chuàng)建方式
這篇文章主要介紹了Oracle??range時(shí)間范圍自動(dòng)分區(qū)的創(chuàng)建方式,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-04-04

