共計 11630 個字符,預(yù)計需要花費 30 分鐘才能閱讀完成。
本篇內(nèi)容主要講解“Oracle SQL 性能優(yōu)化的方法有哪些”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓丸趣 TV 小編來帶大家學(xué)習(xí)“Oracle SQL 性能優(yōu)化的方法有哪些”吧!
1. SQL 語句執(zhí)行步驟
語法分析 語義分析 視圖轉(zhuǎn)換 表達式轉(zhuǎn)換 選擇優(yōu)化器 選擇連接方式 選擇連接順序 選擇數(shù)據(jù)的搜索路徑 運行“執(zhí)行計劃”
2. 選用適合的 Oracle 優(yōu)化器
RULE(基于規(guī)則)、COST(基于成本)、CHOOSE(選擇性)
3. 訪問 Table 的方式
全表掃描
全表掃描就是順序地訪問表中每條記錄,ORACLE 采用一次讀入多個數(shù)據(jù)塊 (database block) 的方式優(yōu)化全表掃描。
通過 ROWID 訪問表
ROWID 包含了表中記錄的物理位置信息,ORACLE 采用索引實現(xiàn)了數(shù)據(jù)和存放數(shù)據(jù)的物理位置 (ROWID) 之間的聯(lián)系,通常索引提供了快速訪問 ROWID 的方法,因此那些基于索引列的查詢就可以得到性能上的提高。
4. 共享 SQL 語句
Oracle 提供對執(zhí)行過的 SQL 語句進行高速緩沖的機制。被解析過并且確定了執(zhí)行路徑的 SQL 語句存放在 SGA 的共享池中。
Oracle 執(zhí)行一個 SQL 語句之前每次先從 SGA 共享池中查找是否有緩沖的 SQL 語句,如果有則直接執(zhí)行該 SQL 語句。
可以通過適當調(diào)整 SGA 共享池大小來達到提高 Oracle 執(zhí)行性能的目的。
5. 選擇最有效率的表名順序
ORACLE 的解析器按照從右到左的順序處理 FROM 子句中的表名,因此 FROM 子句中寫在最后的表 (基礎(chǔ)表 driving table) 將被最先處理。
當 ORACLE 處理多個表時,會運用排序及合并的方式連接它們,并且是從右往左的順序處理 FROM 子句。首先,掃描第一個表 (FROM 子句中最后的那個表) 并對記錄進行排序,然后掃描第二個表(FROM 子句中倒數(shù)第二個表),最后將所有從第二個表中檢索出的記錄與第一個表中合適記錄進行合并。
只在基于規(guī)則的優(yōu)化器中有效。
舉例:
表 TAB1 16,384 條記錄
表 TAB2 1 條記錄
/* 選擇 TAB2 作為基礎(chǔ)表 (最好的方法)*/ SELECT COUNT(*) FROM TAB1,TAB2 /* 執(zhí)行時間 0.96 秒 */ /* 選擇 TAB1 作為基礎(chǔ)表 (不佳的方法)*/ SELECT COUNT(*) FROM TAB2,TAB1 /* 執(zhí)行時間 26.09 秒 */
如果有 3 個以上的表連接查詢, 那就需要選擇交叉表 (intersection table) 作為基礎(chǔ)表, 交叉表是指那個被其他表所引用的表。
/* 高效的 SQL*/ SELECT * FROM LOCATION L, CATEGORY C, EMP E WHERE E.EMP_NO BETWEEN 1000 AND 2000 AND E.CAT_NO = C.CAT_NO AND E.LOCN = L.LOCN
將比下列 SQL 更有效率
/* 低效的 SQL*/ SELECT * FROM EMP E, LOCATION L, CATEGORY C WHERE E.CAT_NO = C.CAT_NO AND E.LOCN = L.LOCN AND E.EMP_NO BETWEEN 1000 AND 2000
6. Where 子句中的連接順序
Oracle 采用自下而上或自右向左的順序解析 WHERE 子句。根據(jù)這個原理, 表之間的連接必須寫在其他 WHERE 條件之前,那些可以過濾掉最大數(shù)量記錄的條件必須寫在 WHERE 子句的末尾。
/* 低效, 執(zhí)行時間 156.3 秒 */ SELECT Column1,Column2 FROM EMP EWHERE E.SAL 50000 AND E.JOB = MANAGER AND 25 (SELECT COUNT(*) FROM EMP WHERE MGR = E.EMPNO) /* 高效, 執(zhí)行時間 10.6 秒 */ SELECT Column1,Column2FROM EMP E WHERE 25 (SELECT COUNT(*) FROM EMP WHERE MGR=E.EMPNO) AND E.SAL 50000 AND E.JOB = MANAGER
7. SELECT 子句中避免使用“*”
Oracle 在解析 SQL 語句的時候,對于“*”將通過查詢數(shù)據(jù)庫字典來將其轉(zhuǎn)換成對應(yīng)的列名。
如果在 Select 子句中需要列出所有的 Column 時,建議列出所有的 Column 名稱,而不是簡單的用“*”來替代,這樣可以減少多于的數(shù)據(jù)庫查詢開銷。
8. 減少訪問數(shù)據(jù)庫的次數(shù)
當執(zhí)行每條 SQL 語句時, ORACLE 在內(nèi)部執(zhí)行了許多工作:解析 SQL 語句 估算索引的利用率 綁定變量 讀數(shù)據(jù)塊等等
由此可見, 減少訪問數(shù)據(jù)庫的次數(shù) , 就能實際上減少 ORACLE 的工作量。
9. 整個簡單無關(guān)聯(lián)的數(shù)據(jù)庫訪問
如果有幾個簡單的數(shù)據(jù)庫查詢語句,你可以把它們整合到一個查詢中(即使它們之間沒有關(guān)系),以減少多于的數(shù)據(jù)庫 IO 開銷。
雖然采取這種方法,效率得到提高,但是程序的可讀性大大降低,所以還是要權(quán)衡之間的利弊。
10. 使用 Truncate 而非 Delete
Delete 表中記錄的時候,Oracle 會在 Rollback 段中保存刪除信息以備恢復(fù)。Truncate 刪除表中記錄的時候不保存刪除信息,不能恢復(fù)。因此 Truncate 刪除記錄比 Delete 快,而且占用資源少。
刪除表中記錄的時候,如果不需要恢復(fù)的情況之下應(yīng)該盡量使用 Truncate 而不是 Delete。
Truncate 僅適用于刪除全表的記錄。
11. 盡量多使用 COMMIT
只要有可能, 在程序中盡量多使用 COMMIT, 這樣程序的性能得到提高, 需求也會因為 COMMIT 所釋放的資源而減少。
COMMIT 所釋放的資源:
回滾段上用于恢復(fù)數(shù)據(jù)的信息.
被程序語句獲得的鎖
redo log buffer 中的空間
ORACLE 為管理上述 3 種資源中的內(nèi)部花費
12. 計算記錄條數(shù)
Select count(*) from tablename; Select count(1) from tablename; Select count(column) from tablename;
一般認為,在沒有主鍵索引的情況之下,第二種 COUNT(1)方式最快。如果只有一列且無索引 COUNT(*)反而比較快,如果有索引列,當然是使用索引列 COUNT(column)最快。
13. 用 Where 子句替換 Having 子句
避免使用 HAVING 子句,HAVING 只會在檢索出所有記錄之后才對結(jié)果集進行過濾。這個處理需要排序、總計等操作。如果能通過 WHERE 子句限制記錄的數(shù)目,就能減少這方面的開銷。
14. 減少對表的查詢操作
在含有子查詢的 SQL 語句中,要注意減少對表的查詢操作。
/* 低效 SQL*/ 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)
/* 高效 SQL*/ SELECT TAB_NAME FROM TABLES WHERE (TAB_NAME,DB_VER)=( SELECT TAB_NAME,DB_VER FROM TAB_COLUMNS WHERE VERSION = 604)
15. 使用表的別名(Alias)
當在 SQL 語句中連接多個表時, 請使用表的別名并把別名前綴于每個 Column 上. 這樣一來, 就可以減少解析的時間并減少那些由 Column 歧義引起的語法錯誤。
Column 歧義指的是由于 SQL 中不同的表具有相同的 Column 名, 當 SQL 語句中出現(xiàn)這個 Column 時,SQL 解析器無法判斷這個 Column 的歸屬。
16. 用 EXISTS 替代 IN
在許多基于基礎(chǔ)表的查詢中,為了滿足一個條件,往往需要對另一個表進行聯(lián)接。在這種情況下,使用 EXISTS(或 NOT EXISTS)通常將提高查詢的效率。
/* 低效 SQL*/ SELECT * FROM EMP WHERE EMPNO 0 AND DEPTNO IN ( SELECT DEPTNO FROM DEPT WHERE LOC = MELB)
/* 高效 SQL*/ SELECT * FROM EMP WHERE EMPNO 0 AND EXISTS (SELECT 1 FROM DEPT WHERE DEPT.DEPTNO = EMP.DEPTNO AND LOC = MELB)
17. 用 NOT EXISTS 替代 NOT IN
在子查詢中,NOT IN 子句將執(zhí)行一個內(nèi)部的排序和合并,對子查詢中的表執(zhí)行一個全表遍歷,因此是非常低效的。
為了避免使用 NOT IN,可以把它改寫成外連接(Outer Joins)或者 NOT EXISTS。
/* 低效 SQL*/ SELECT * FROM EMP WHERE DEPT_NO NOT IN ( SELECT DEPT_NO FROM DEPT WHERE DEPT_CAT= A)
/* 高效 SQL*/ SELECT * FROM EMP E WHERE NOT EXISTS (SELECT 1 FROM DEPT D WHERE D.DEPT_NO = E.DEPT_NO AND DEPT_CAT = A)
18. 用表連接替換 EXISTS
通常來說,采用表連接的方式比 EXISTS 更有效率。
/* 低效 SQL*/ SELECT ENAME FROM EMP E WHERE EXISTS (SELECT 1 FROM DEPT WHERE DEPT_NO = E.DEPT_NO AND DEPT_CAT = A)
/* 高效 SQL*/ SELECT ENAME FROM DEPT D,EMP E WHERE E.DEPT_NO = D.DEPT_NO AND D.DEPT_CAT = A
19. 用 EXISTS 替換 DISTINCT
當提交一個包含對多表信息(比如部門表和雇員表)的查詢時,避免在 SELECT 子句中使用 DISTINCT。一般可以考慮用 EXIST 替換。
EXISTS 使查詢更為迅速,因為 RDBMS 核心模塊將在子查詢的條件一旦滿足后,立刻返回結(jié)果。
/* 低效 SQL*/ SELECT DISTINCT D.DEPT_NO,D.DEPT_NAME FROM DEPT D,EMP E WHERE D.DEPT_NO = E.DEPT_NO
/* 高效 SQL*/ SELECT D.DEPT_NO,D.DEPT_NAME FROM DEPT D WHERE EXISTS (SELECT 1 FROM EMP E WHERE E.DEPT_NO = D.DEPT_NO)
20. 識別低效的 SQL 語句
下面的 SQL 工具可以找出低效 SQL,前提是需要 DBA 權(quán)限,否則查詢不了。
SELECT EXECUTIONS, DISK_READS, BUFFER_GETS, ROUND ((BUFFER_GETS-DISK_READS)/BUFFER_GETS, 2) Hit_radio, ROUND (DISK_READS/EXECUTIONS, 2) Reads_per_run, SQL_TEXT FROM V$SQLAREA WHERE EXECUTIONS 0 AND BUFFER_GETS 0 AND (BUFFER_GETS-DISK_READS)/BUFFER_GETS 0.8 ORDER BY 4 DESC
另外也可以使用 SQL Trace 工具來收集正在執(zhí)行的 SQL 的性能狀態(tài)數(shù)據(jù),包括解析次數(shù),執(zhí)行次數(shù),CPU 使用時間等。
21. 用 Explain Plan 分析 SQL 語句
EXPLAIN PLAN 是一個很好的分析 SQL 語句的工具, 它甚至可以在不執(zhí)行 SQL 的情況下分析語句. 通過分析, 我們就可以知道 ORACLE 是怎么樣連接表, 使用什么方式掃描表 (索引掃描或全表掃描) 以及使用到的索引名稱。
22. SQL PLUS 的 TRACE
SQL list SELECT * FROM dept, emp WHERE emp.deptno = dept.deptno SQL set autotrace traceonly /*traceonly 可以不顯示執(zhí)行結(jié)果 */ SQL / rows selected. Execution Plan ---------------------------------------------------------- SELECT STATEMENT Optimizer=CHOOSE 0 NESTED LOOPS 1 TABLE ACCESS (FULL) OF EMP 1 TABLE ACCESS (BY INDEX ROWID) OF DEPT 3 INDEX (UNIQUE SCAN) OF PK_DEPT (UNIQUE)
23. 用索引提高效率
(1)特點
優(yōu)點:提高效率 主鍵的唯一性驗證
代價:需要空間存儲 定期維護
重構(gòu)索引:
ALTER INDEX INDEXNAME REBUILD TABLESPACENAME
(2)Oracle 對索引有兩種訪問模式
索引唯一掃描 (Index Unique Scan)
索引范圍掃描 (Index Range Scan)
(3)基礎(chǔ)表的選擇
基礎(chǔ)表 (Driving Table) 是指被最先訪問的表(通常以全表掃描的方式被訪問)。根據(jù)優(yōu)化器的不同,SQL 語句中基礎(chǔ)表的選擇是不一樣的。
如果你使用的是 CBO (COST BASED OPTIMIZER),優(yōu)化器會檢查 SQL 語句中的每個表的物理大小,索引的狀態(tài),然后選用花費最低的執(zhí)行路徑。
如果你用 RBO (RULE BASED OPTIMIZER),并且所有的連接條件都有索引對應(yīng),在這種情況下,基礎(chǔ)表就是 FROM 子句中列在最后的那個表。
(4)多個平等的索引
當 SQL 語句的執(zhí)行路徑可以使用分布在多個表上的多個索引時,ORACLE 會同時使用多個索引并在運行時對它們的記錄進行合并,檢索出僅對全部索引有效的記錄。
在 ORACLE 選擇執(zhí)行路徑時,唯一性索引的等級高于非唯一性索引。然而這個規(guī)則只有當 WHERE 子句中索引列和常量比較才有效。如果索引列和其他表的索引類相比較。這種子句在優(yōu)化器中的等級是非常低的。
如果不同表中兩個相同等級的索引將被引用,F(xiàn)ROM 子句中表的順序?qū)Q定哪個會被率先使用。FROM 子句中最后的表的索引將有最高的優(yōu)先級。
如果相同表中兩個相同等級的索引將被引用,WHERE 子句中最先被引用的索引將有最高的優(yōu)先級。
(5)等式比較優(yōu)先于范圍比較
DEPTNO 上有一個非唯一性索引,EMP_CAT 也有一個非唯一性索引。
SELECT ENAME FROM EMP WHERE DEPTNO 20 AND EMP_CAT = A
這里只有 EMP_CAT 索引被用到, 然后所有的記錄將逐條與 DEPTNO 條件進行比較. 執(zhí)行路徑如下:
TABLE ACCESS BY ROWID ON EMP INDEX RANGE SCAN ON CAT_IDX
即使是唯一性索引,如果做范圍比較,其優(yōu)先級也低于非唯一性索引的等式比較。
(6)不明確的索引等級
當 ORACLE 無法判斷索引的等級高低差別,優(yōu)化器將只使用一個索引, 它就是在 WHERE 子句中被列在最前面的。
DEPTNO 上有一個非唯一性索引,EMP_CAT 也有一個非唯一性索引。
SELECT ENAME FROM EMP WHERE DEPTNO 20 AND EMP_CAT A
這里, ORACLE 只用到了 DEPT_NO 索引. 執(zhí)行路徑如下:
TABLE ACCESS BY ROWID ON EMP INDEX RANGE SCAN ON DEPT_IDX
(7)強制索引失效
如果兩個或以上索引具有相同的等級,你可以強制命令 ORACLE 優(yōu)化器使用其中的一個(通過它, 檢索出的記錄數(shù)量少)。
SELECT ENAME FROM EMP WHERE EMPNO = 7935 AND DEPTNO + 0 = 10 /*DEPTNO 上的索引將失效 */ AND EMP_TYPE || = A /*EMP_TYPE 上的索引將失效 */
(8)避免在索引列上使用計算
WHERE 子句中,如果索引列是函數(shù)的一部分。優(yōu)化器將不使用索引而使用全表掃描。
/* 低效 SQL*/ SELECT * FROM DEPT WHERE SAL * 12 25000;
/* 高效 SQL*/ SELECT * FROM DEPT WHERE SAL 25000/12;
(9)自動選擇索引
如果表中有兩個以上(包括兩個)索引,其中有一個唯一性索引,而其他是非唯一性索引。在這種情況下,ORACLE 將使用唯一性索引而完全忽略非唯一性索引。
SELECT ENAME FROM EMP WHERE EMPNO = 2326 AND DEPTNO = 20;
這里,只有 EMPNO 上的索引是唯一性的,所以 EMPNO 索引將用來檢索記錄。
TABLE ACCESS BY ROWID ON EMP INDEX UNIQUE SCAN ON EMP_NO_IDX
(10)避免在索引列上使用 NOT
通常,我們要避免在索引列上使用 NOT,NOT 會產(chǎn)生在和在索引列上使用函數(shù)相同的影響。當 ORACLE 遇到 NOT,它就會停止使用索引轉(zhuǎn)而執(zhí)行全表掃描。
/* 低效 SQL: (這里,不使用索引)*/ SELECT * FROM DEPT WHERE NOT DEPT_CODE = 0
/* 高效 SQL: (這里,使用索引)*/ SELECT * FROM DEPT WHERE DEPT_CODE 0
24. 用 = 替代
如果 DEPTNO 上有一個索引
/* 高效 SQL*/ SELECT * FROM EMP WHERE DEPTNO =4
/* 低效 SQL*/ SELECT * FROM EMP WHERE DEPTNO 3
兩者的區(qū)別在于,前者 DBMS 將直接跳到第一個 DEPT 等于 4 的記錄,而后者將首先定位到 DEPTNO 等于 3 的記錄并且向前掃描到第一個 DEPT 大于 3 的記錄.
25. 用 Union 替換 OR(適用于索引列)
通常情況下,用 UNION 替換 WHERE 子句中的 OR 將會起到較好的效果。對索引列使用 OR 將造成全表掃描。注意,以上規(guī)則只針對多個索引列有效。
/* 高效 SQL*/ SELECT LOC_ID , LOC_DESC , REGION FROM LOCATION WHERE LOC_ID = 10 UNIONS ELECT LOC_ID , LOC_DESC , REGION FROM LOCATION WHERE REGION = MELBOURNE
/* 低效 SQL*/ SELECT LOC_ID,LOC_DESC,REGION FROM LOCATION WHERE LOC_ID = 10 OR REGION = MELBOURNE
26. 用 IN 替換 OR
/* 低效 SQL*/ SELECT * FROM LOCATION WHERE LOC_ID = 10 OR LOC_ID = 20 OR LOC_ID = 30
/* 高效 SQL*/ SELECT * FROM LOCATION WHERE LOC_IN IN (10,20,30)
實際的執(zhí)行效果還須檢驗,在 ORACLE8i 下,兩者的執(zhí)行路徑似乎是相同的。
27. 避免在索引列上使用 is null 和 is not null
避免在索引中使用任何可以為空的列,ORACLE 將無法使用該索引。
/* 低效 SQL:(索引失效)*/ SELECT * FROM DEPARTMENT WHERE DEPT_CODE IS NOT NULL;
/* 高效 SQL:(索引有效)*/ SELECT * FROM DEPARTMENT WHERE DEPT_CODE
28. 總是使用索引的第一個列
如果索引是建立在多個列上,只有在它的第一個列 (leading column) 被 where 子句引用時,優(yōu)化器才會選擇使用該索引。
SQL create index multindex on multiindexusage(inda,indb); Index created. SQL select * from multiindexusage where indb = 1; Execution Plan ---------------------------------------------------------- SELECT STATEMENT Optimizer=CHOOSE 0 TABLE ACCESS (FULL) OF MULTIINDEXUSAGE lsquo;
很明顯, 當僅引用索引的第二個列時, 優(yōu)化器使用了全表掃描而忽略了索引。
29. 使用 UNION ALL 替代 UNION
當 SQL 語句需要 UNION 兩個查詢結(jié)果集合時,這兩個結(jié)果集合會以 UNION-ALL 的方式被合并,然后在輸出最終結(jié)果前進行排序。如果用 UNION ALL 替代 UNION,這樣排序就不是必要了,效率就會因此得到提高。
由于 UNION ALL 的結(jié)果沒有經(jīng)過排序,而且不過濾重復(fù)的記錄,因此是否進行替換需要根據(jù)業(yè)務(wù)需求而定。
30. 對 UNION 的優(yōu)化
由于 UNION 會對查詢結(jié)果進行排序,而且過濾重復(fù)記錄,因此其執(zhí)行效率沒有 UNION ALL 高。UNION 操作會使用到 SORT_AREA_SIZE 內(nèi)存塊,因此對這塊內(nèi)存的優(yōu)化也非常重要。
可以使用下面的 SQL 來查詢排序的消耗量:
select substr(name,1,25) Sort Area Name, substr(value,1,15) Value from v$sysstat where name like sort%
31. 避免改變索引列的類型
當比較不同數(shù)據(jù)類型的數(shù)據(jù)時,ORACLE 自動對列進行簡單的類型轉(zhuǎn)換。
/* 假設(shè) EMP_TYPE 是一個字符類型的索引列.*/ SELECT * FROM EMP WHERE EMP_TYPE = 123 /* 這個語句被 ORACLE 轉(zhuǎn)換為:*/ SELECT * FROM EMP WHERE TO_NUMBER(EMP_TYPE)=123
因為內(nèi)部發(fā)生的類型轉(zhuǎn)換,這個索引將不會被用到。
幾點注意:
當比較不同數(shù)據(jù)類型的數(shù)據(jù)時,ORACLE 自動對列進行簡單的類型轉(zhuǎn)換。
如果在索引列上面進行了隱式類型轉(zhuǎn)換,在查詢的時候?qū)⒉粫玫剿饕?/p>
注意當字符和數(shù)值比較時,ORACLE 會優(yōu)先轉(zhuǎn)換數(shù)值類型到字符類型。
為了避免 ORACLE 對 SQL 進行隱式的類型轉(zhuǎn)換,最好把類型轉(zhuǎn)換用顯式表現(xiàn)出來。
32. 使用提示(Hints)
FULL hint 告訴 ORACLE 使用全表掃描的方式訪問指定表。
ROWID hint 告訴 ORACLE 使用 TABLE ACCESS BY ROWID 的操作訪問表。
CACHE hint 來告訴優(yōu)化器把查詢結(jié)果數(shù)據(jù)保留在 SGA 中。
INDEX Hint 告訴 ORACLE 使用基于索引的掃描方式。
其他的 Oracle Hints
ALL_ROWS
FIRST_ROWS
RULE
USE_NL
USE_MERGE
USE_HASH 等等。
這是一個很有技巧性的工作。建議只針對特定的,少數(shù)的 SQL 進行 hint 的優(yōu)化。
33. 幾種不能使用索引的 WHERE 子句
(1)下面的例子中,lsquo;!= rsquo; 將不使用索引,索引只能告訴你什么存在于表中,而不能告訴你什么不存在于表中。
/* 不使用索引 */ SELECT ACCOUNT_NAME FROM TRANSACTION WHERE AMOUNT !=0;
/* 使用索引 */ SELECT ACCOUNT_NAME FROM TRANSACTION WHERE AMOUNT 0;
(2)下面的例子中,lsquo;|| rsquo; 是字符連接函數(shù)。就象其他函數(shù)那樣,停用了索引。
/* 不使用索引 */ SELECT ACCOUNT_NAME,AMOUNT FROM TRANSACTION WHERE ACCOUNT_NAME||ACCOUNT_TYPE= AMEXA;
/* 使用索引 */ SELECT ACCOUNT_NAME,AMOUNT FROM TRANSACTION WHERE ACCOUNT_NAME = AMEX AND ACCOUNT_TYPE= A;
(3)下面的例子中,lsquo;+ rsquo; 是數(shù)學(xué)函數(shù)。就象其他數(shù)學(xué)函數(shù)那樣,停用了索引。
/* 不使用索引 */ SELECT ACCOUNT_NAME,AMOUNT FROM TRANSACTION WHERE AMOUNT + 3000 5000;
/* 使用索引 */ SELECT ACCOUNT_NAME,AMOUNT FROM TRANSACTION WHERE AMOUNT 2000 ;
(4)下面的例子中,相同的索引列不能互相比較,這將會啟用全表掃描。
/* 不使用索引 */ SELECT ACCOUNT_NAME, AMOUNT FROM TRANSACTION WHERE ACCOUNT_NAME = NVL(:ACC_NAME, ACCOUNT_NAME)
/* 使用索引 */ SELECT ACCOUNT_NAME,AMOUNT FROM TRANSACTION WHERE ACCOUNT_NAME LIKE NVL(:ACC_NAME, rsquo;% rsquo;)
34. 連接多個掃描
如果對一個列和一組有限的值進行比較,優(yōu)化器可能執(zhí)行多次掃描并對結(jié)果進行合并連接。
舉例:
SELECT * FROM LODGING WHERE MANAGER IN (BILL GATES , KEN MULLER)
優(yōu)化器可能將它轉(zhuǎn)換成以下形式:
SELECT * FROM LODGING WHERE MANAGER = BILL GATES OR MANAGER = KEN MULLER
35. CBO 下使用更具選擇性的索引
基于成本的優(yōu)化器(CBO,Cost-Based Optimizer)對索引的選擇性進行判斷來決定索引的使用是否能提高效率。
如果檢索數(shù)據(jù)量超過 30% 的表中記錄數(shù),使用索引將沒有顯著的效率提高。
在特定情況下,使用索引也許會比全表掃描慢。而通常情況下,使用索引比全表掃描要塊幾倍乃至幾千倍!
36. 避免使用耗費資源的操作
帶有 DISTINCT,UNION,MINUS,INTERSECT,ORDER BY 的 SQL 語句會啟動 SQL 引擎執(zhí)行耗費資源的排序(SORT)功能。DISTINCT 需要一次排序操作,而其他的至少需要執(zhí)行兩次排序。
通常,帶有 UNION,MINUS,INTERSECT 的 SQL 語句都可以用其他方式重寫。
37. 優(yōu)化 GROUP BY
提高 GROUP BY 語句的效率,可以通過將不需要的記錄在 GROUP BY 之前過濾掉。
/* 低效 SQL*/ SELECT JOB,AVG(SAL)FROM EMP GROUP BY JOB HAVING JOB = PRESIDENT OR JOB = MANAGER
/* 高效 SQL*/ SELECT JOB,AVG(SAL)FROM EMP WHERE JOB = PRESIDENT OR JOB = MANAGER GROUP BY JOB
38. 使用日期
當使用日期時,需要注意如果有超過 5 位小數(shù)加到日期上,這個日期會進到下一天!
SELECT TO_DATE(01-JAN-93 +.99999) FROM DUAL 結(jié)果: 01-JAN-93 23:59:59 SELECT TO_DATE(01-JAN-93 +.999999) FROM DUAL 結(jié)果: 02-JAN-93 00:00:00
39. 使用顯示游標(CURSORS)
使用隱式的游標,將會執(zhí)行兩次操作。第一次檢索記錄,第二次檢查 TOO MANY ROWS 這個 exception。而顯式游標不執(zhí)行第二次操作。
40. 分離表和索引
總是將你的表和索引建立在不同的表空間內(nèi)(TABLESPACES)。
決不要將不屬于 ORACLE 內(nèi)部系統(tǒng)的對象存放到 SYSTEM 表空間里。
確保數(shù)據(jù)表空間和索引表空間置于不同的硬盤上。
到此,相信大家對“Oracle SQL 性能優(yōu)化的方法有哪些”有了更深的了解,不妨來實際操作一番吧!這里是丸趣 TV 網(wǎng)站,更多相關(guān)內(nèi)容可以進入相關(guān)頻道進行查詢,關(guān)注我們,繼續(xù)學(xué)習(xí)!