oracle_SQL優化.doc_第1頁
oracle_SQL優化.doc_第2頁
oracle_SQL優化.doc_第3頁
oracle_SQL優化.doc_第4頁
oracle_SQL優化.doc_第5頁
已閱讀5頁,還剩29頁未讀 繼續免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

Oracle sql 性能優化調整性能優化調整 1 訪問訪問 Table 的方式的方式 ORACLE 采用兩種訪問表中記錄的方式 a 全表掃描 全表掃描就是順序地訪問表中每條記錄 ORACLE 采用一次讀入多個數據塊 database block 的方式優化全表掃描 b 通過 ROWID 訪問表 你可以采用基于 ROWID 的訪問方式情況 提高訪問表的效率 ROWID 包含了表中 記錄的物理位置信息 ORACLE 采用索引 INDEX 實現了數據和存放數據的物理位置 ROWID 之間的聯系 通常索引提供了快速訪問 ROWID 的方法 因此那些基于索引列的查詢 就可以得到性能上的提高 2 選擇選擇最有效率的表名最有效率的表名順順序序 ORACLE 的解析器按照從右到左的順序處理的解析器按照從右到左的順序處理 FROM 子句中的表名子句中的表名 因此 FROM 子句中寫在 最后的表 基礎表 driving table 將被最先處理 在 FROM 子句中包含多個表的情況下 你必須 選擇記錄條數最少的表作為基礎表 當 ORACLE 處理多個表時 會運用排序及合并的方式連 接它們 首先 掃描第一個表 FROM 子句中最后的那個表 并對記錄進行派序 然后掃描第二個 表 FROM 子句中最后第二個表 最后將所有從第二個表中檢索出的記錄與第一個表中合適 記錄進行合并 例如 表 TAB1 16 384 條記錄 表 TAB2 1 條記錄 選擇 TAB2 作為基礎表 最好的方法 select count from tab1 tab2 執行時間 0 96 秒 選擇 TAB2 作為基礎表 不佳的方法 select count from tab2 tab1 執行時間 26 09 秒 如果有 3 個以上的表連接查詢 那就需要選擇交叉表 intersection table 作為基礎表 交叉表是指 那個被其他表所引用的表 例如 EMP 表描述了 LOCATION 表和 CATEGORY 表的交集 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 更有效率 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 3 WHERE 子句中的連接順序 子句中的連接順序 ORACLE 采用自下而上的順序解析采用自下而上的順序解析 WHERE 子句子句 根據這個原理 表之間的連接必須寫在其他 WHERE 條件之前 那些可以過濾掉最大數量記錄的條件必須寫在 WHERE 子句的末尾 例如 低效 執行時間 156 3 秒 SELECT FROM EMP E WHERE SAL 50000 AND JOB MANAGER AND 25 SELECT COUNT FROM EMP WHERE MGR E EMPNO 高效 執行時間 10 6 秒 SELECT FROM EMP E WHERE 25 50000 AND JOB MANAGER 4 SELECT 子句中避免使用子句中避免使用 當你想在 SELECT 子句中列出所有的 COLUMN 時 使用動態 SQL 列引用 是一個方便的 方法 不幸的是 這是一個非常低效的方法 實際上 ORACLE 在解析的過程中 會將 依次轉 換成所有的列名 這個工作是通過查詢數據字典完成的 這意味著將耗費更多的時間 5 減少訪問數據庫的次數減少訪問數據庫的次數 當執行每條 SQL 語句時 ORACLE 在內部執行了許多工作 解析 SQL 語句 估算索引的利 用率 綁定變量 讀數據塊等等 由此可見 減少訪問數據庫的次數 就能實際上減少 ORACLE 的工作量 例如 以下有三種方法可以檢索出雇員號等于 0342 或 0291 的職員 方法 1 最低效 SELECT EMP NAME SALARY GRADE FROM EMP WHERE EMP NO 342 SELECT EMP NAME SALARY GRADE FROM EMP WHERE EMP NO 291 方法 2 次低效 DECLARE CURSOR C1 E NO NUMBER IS SELECT EMP NAME SALARY GRADE FROM EMP WHERE EMP NO E NO BEGIN OPEN C1 342 FETCH C1 INTO OPEN C1 291 FETCH C1 INTO CLOSE C1 END 方法 3 高效 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 注意注意 在 SQL Plus SQL Forms 和 Pro C 中重新設置 ARRAYSIZE 參數 可以增加每次數據 庫訪問的檢索數據量 建議值為 200 6 使用使用 DECODE 函數來減少處理時間函數來減少處理時間 使用 DECODE 函數可以避免重復掃描相同記錄或重復連接相同的表 例如 SELECT COUNT SUM SAL FROM EMP WHERE DEPT NO 0020 AND ENAME LIKE SMITH SELECT COUNT SUM SAL FROM EMP WHERE DEPT NO 0030 AND ENAME LIKE SMITH 你可以用 DECODE 函數高效地得到相同結果 SELECT COUNT DECODE DEPT NO 0020 X NULL D0020 COUNT COUNT DECODE DEPT NO 0030 X NULL D0030 COUNT SUM DECODE DEPT NO 0020 SAL NULL D0020 SAL SUM DECODE DEPT NO 0030 SAL NULL D0030 SAL FROM EMP WHERE ENAME LIKE SMITH 類似的 DECODE 函數也可以運用于 GROUP BY 和 ORDER BY 子句中 7 整合簡單整合簡單 無關聯的數據庫訪問無關聯的數據庫訪問 如果你有幾個簡單的數據庫查詢語句 你可以把它們整合到一個查詢中 即使它們之間沒有關 系 例如 SELECT NAME FROM EMP WHERE EMP NO 1234 SELECT NAME FROM DPT WHERE DPT NO 10 SELECT NAME FROM CAT WHERE CAT TYPE RD 上面的 3 個查詢可以被合并成一個 SELECT E NAME D NAME C NAME FROM CAT C DPT D EMP E DUAL X WHERE NVL X X DUMMY NVL X E ROWID AND NVL X X DUMMY NVL X D ROWID AND NVL X X DUMMY NVL X C ROWID AND E EMP NO 1234 AND D DEPT NO 10 AND C CAT TYPE RD 雖然采取這種方法雖然采取這種方法 效率得到提高效率得到提高 但是程序的可讀性大大降低但是程序的可讀性大大降低 所以還是要權衡之間的利弊所以還是要權衡之間的利弊 8 刪除重復記錄刪除重復記錄 最高效的刪除重復記錄方法 因為使用了 ROWID DELETE FROM EMP E WHERE E ROWID SELECT MIN X ROWID FROM EMP X WHERE X EMP NO E EMP NO 9 用用 TRUNCATE 替代替代 DELETE 當刪除表中的記錄時 在通常情況下 回滾段 rollback segments 用來存放可以被恢復的信 息 如果你沒有 COMMIT 事務 ORACLE 會將數據恢復到刪除之前的狀態 準確地說是恢復到 執行刪除命令之前的狀況 而當運用 TRUNCATE 時 回滾段不再存放任何可被恢復的信息 當命令運行后 數據不能被 恢復 因此很少的資源被調用 執行時間也會很短 TRUNCATE 只在刪除全表適用只在刪除全表適用 TRUNCATE 是是 DDL 不是不是 DML 10 盡量多使用盡量多使用 COMMIT 只要有可能 在程序中盡量多使用 COMMIT 這樣程序的性能得到提高 需求也會因為 COMMIT 所釋放的資源而減少 COMMIT 所釋放的資源 a 回滾段上用于恢復數據的信息 b 被程序語句獲得的鎖 c redo log buffer 中的空間 d ORACLE 為管理上述 3 種資源中的內部花費 在使用在使用 COMMIT 時必須要注意到事務的完整性時必須要注意到事務的完整性 現實中效率和事務完整性往往是魚和熊掌現實中效率和事務完整性往往是魚和熊掌 不可得兼不可得兼 11 計算記錄條數計算記錄條數 和一般的觀點相反 count 比 count 1 稍快 當然如果可以通過索引檢索 對索引列的計 數仍舊是最快的 例如 COUNT EMPNO 在在 CSDN 論壇中論壇中 曾經對此有過相當熱烈的討論曾經對此有過相當熱烈的討論 作者的觀點并不十分準確作者的觀點并不十分準確 通過實際的測試通過實際的測試 上上 述三種方法并沒有顯著的性能差別述三種方法并沒有顯著的性能差別 12 用用 Where 子句替換子句替換 HAVING 子句子句 避免使用 HAVING 子句 HAVING 只會在檢索出所有記錄之后才對結果集進行過濾 這個 處理需要排序 總計等操作 如果能通過 WHERE 子句限制記錄的數目 那就能減少這方面的開銷 例如 低效 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 中的條件一般用于對一些集合函數的比較中的條件一般用于對一些集合函數的比較 如如 COUNT 等等等等 除此而外除此而外 一般的條件一般的條件 應該寫在應該寫在 WHERE 子句中子句中 Having 用法 用法 數據表 student 表結構 Field Name DataType Len id int 20 name varchar 25 major varchar 25 score int 20 sex varchar 20 rn 表數據 編號 姓名 專業 學分 性別 id name major score sex 1 jak Chinese 40 f 2 rain Math 89 m 3 leo Phy 78 f 4 jak Math 76 f 5 rain Chinese 56 m 6 leo Math 97 f 7 jak Phy 45 f 8 jak Draw 87 f 9 leo Chinese 45 f 現在我們要得到一個視圖 要求查詢性別為男生 并且列出每個學生的總成績 SQL select s sum s score from student s where sex f group by s name Result id name major score sex sum s score 1 jak Chinese 40 f 248 3 leo Phy 78 f 220 可以看到總共查到有兩組 兩組的學生分別是 jak 和 leo 每一組都是同一個學生 這樣我們就 可以使用聚合函數了 只有使用了 group by 語句 才能使用如 count sum 之類的聚合函數 下面我們再對上面的結果做進一步的篩選 只顯示總分數大于 230 的學生 SQL select s sum s score from student s where sex f group by s name having sum s score 230 Result id name major score sex sum s score 1 jak Chinese 40 f 248 可見 having 于 where 的功能差不多 結論 1 WHERE 子句用來篩選 FROM 子句中指定的操作所產生的行 2 GROUP BY 子句用來分組 WHERE 子句的輸出 3 HAVING 子句用來從分組的結果中篩選行 13 減少對表的查詢減少對表的查詢 在含有子查詢的 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 高效 SELECT TAB NAME FROM TABLES WHERE TAB NAME DB VER SELECT TAB NAME DB VER FROM TAB COLUMNS WHERE VERSION 604 Update 多個 Column 例子 低效 UPDATE EMP SET EMP CAT SELECT MAX CATEGORY FROM EMP CATEGORIES SAL RANGE SELECT MAX SAL RANGE FROM EMP CATEGORIES WHERE EMP DEPT 0020 高效 UPDATE EMP SET EMP CAT SAL RANGE SELECT MAX CATEGORY MAX SAL RANGE FROM EMP CATEGORIES WHERE EMP DEPT 0020 14 通過內部函數提高通過內部函數提高 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 往往犧牲了執往往犧牲了執 行效率行效率 能夠掌握上面的運用函數解決問題的方法在實際工作中是非常有意義的能夠掌握上面的運用函數解決問題的方法在實際工作中是非常有意義的 15 使用表的別名使用表的別名 Alias 當在 SQL 語句中連接多個表時 請使用表的別名并把別名前綴于每個 Column 上 這樣一來 就可以減少解析的時間并減少那些由 Column 歧義引起的語法錯誤 Column 歧義指的是由于歧義指的是由于 SQL 中不同的表具有相同的中不同的表具有相同的 Column 名名 當當 SQL 語句中出現這個語句中出現這個 Column 時時 SQL 解析器無法判斷這個解析器無法判斷這個 Column 的歸屬的歸屬 16 用用 EXISTS 替代替代 IN 在許多基于基礎表的查詢中 為了滿足一個條件 往往需要對另一個表進行聯接 在這種情況下 使用 EXISTS 或 NOT EXISTS 通常將提高查詢的效率 低效 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 X FROM DEPT WHERE DEPT DEPTNO EMP DEPTNO AND LOC MELB 相對來說相對來說 用用 NOT EXISTS 替換替換 NOT IN 將更顯著地提高效率將更顯著地提高效率 下一節中將指出下一節中將指出 17 用用 NOT EXISTS 替代替代 NOT IN 在子查詢中 NOT IN 子句將執行一個內部的排序和合并 無論在哪種情況下 NOT IN 都是最 低效的 因為它對子查詢中的表執行了一個全表遍歷 為了避免使用 NOT IN 我們可以把 它改寫成外連接 Outer Joins 或 NOT EXISTS 例如 SELECT FROM EMP WHERE DEPT NO NOT IN SELECT DEPT NO FROM DEPT WHERE DEPT CAT A 為了提高效率 改寫為 方法一 高效 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 18 用表連接替換用表連接替換 EXISTS 通常來說 采用表連接的方式比 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 19 用用 EXISTS 替換替換 DISTINCT 當提交一個包含一對多表信息 比如部門表和雇員表 的查詢時 避免在 SELECT 子句中使用 DISTINCT 一般可以考慮用 EXIST 替換 例如 低效 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 EXISTS 使查詢更為迅速 因為 RDBMS 核心模塊將在子查詢的條件一旦滿足后 立刻返 回結果 20 識別識別 低效執行低效執行 的的 SQL 語句語句 用下列 SQL 工具找出低效 SQL 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 優化的圖形化工具層出不窮優化的圖形化工具層出不窮 但是寫出自己的但是寫出自己的 SQL 工具來解工具來解 決問題始終是一個最好的方法決問題始終是一個最好的方法 21 使用使用 TKPROF 工具來查詢工具來查詢 SQL 性能狀態性能狀態 SQL trace 工具收集正在執行的 SQL 的性能狀態數據并記錄到一個跟蹤文件中 這個跟蹤文件提 供了許多有用的信息 例如解析次數 執行次數 CPU 使用時間等 這些數據將可以用來優化你的系 統 設置 SQL TRACE 在會話級別 有效 ALTER SESSION SET SQL TRACE TRUE 設置 SQL TRACE 在整個數據庫有效仿 你必須將 SQL TRACE 參數在 init ora 中設為 TRUE USER DUMP DEST 參數說明了生成跟蹤文件的目錄 作者并沒有提到作者并沒有提到 TKPROF 的用法的用法 對對 SQL TRACE 的用法也不夠準確的用法也不夠準確 設置設置 SQL TRACE 首首 先要在先要在 init ora 中設定中設定 TIMED STATISTICS 這樣才能得到那些重要的時間狀態這樣才能得到那些重要的時間狀態 生成的生成的 trace 文件是不可讀的文件是不可讀的 所以要用所以要用 TKPROF 工具對其進行轉換工具對其進行轉換 TKPROF 有許多執行參數有許多執行參數 大家可以參大家可以參 考考 ORACLE 手冊來了解具體的配置手冊來了解具體的配置 22 22 用索引提高效率用索引提高效率 索引是表的一個概念部分 用來提高檢索數據的效率 實際上 ORACLE 使用了一個 復雜的自平衡 B tree 結構 通常 通過索引查詢數據比全表掃描要快 當 ORACLE 找 出執行查詢和 Update 語句的最佳路徑時 ORACLE 優化器將使用索引 同樣在聯結多 個表時使用索引也可以提高效率 另一個使用索引的好處是 它提供了主鍵 primary key 的唯一性驗證 除了那些 LONG 或 LONG RAW 數據類型 你可以索引幾乎所有的列 通常 在大型 表中使用索引特別有效 當然 你也會發現 在掃描小表時 使用索引同樣能提高效 率 雖然使用索引能得到查詢效率的提高 但是我們也必須注意到它的代價 索引需 要空間來 存儲 也需要定期維護 每當有記錄在表中增減或索引列被修改時 索引本身也會被 修改 這意味著每條記錄的 INSERT DELETE UPDATE 將為此多付出 4 5 次的磁 盤 I O 因為索引需要額外的存儲空間和處理 那些不必要的索引反而會使查詢反應 時間變慢 定期的重構索引是有必要的定期的重構索引是有必要的 ALTERALTER INDEXINDEX REBUILDREBUILD 23 23 索引的操作索引的操作 ORACLE 對索引有兩種訪問模式 索引唯一掃描 INDEX UNIQUE SCAN 大多數情況下 優化器通過 WHERE 子句訪問 INDEX 例如 表 LODGING 有兩個索引 建立在 LODGING 列上的唯一性索引 LODGING PK 和 建立在 MANAGER 列上的非唯一性索引 LODGING MANAGER SELECT FROM LODGING WHERE LODGING ROSE HILL 在內部 上述 SQL 將被分成兩步執行 首先 LODGING PK 索引將通過索引唯 一掃描的方式被訪問 獲得相對應的 ROWID 通過 ROWID 訪問表的方式 執行下一步 檢索 如果被檢索返回的列包括在 INDEX 列中 ORACLE 將不執行第二步的處理 通過 ROWID 訪問表 因為檢索數據保存在索引中 單單訪問索引就可以完全滿足查詢結 果 下面 SQL 只需要 INDEX UNIQUE SCAN 操作 SELECT LODGING FROM LODGING WHERE LODGING ROSE HILL 索引范圍查詢 INDEX RANGE SCAN 適用于兩種情況 1 基于一個范圍的檢索 2 基于非唯一性索引的檢索 例 1 SELECT LODGING FROM LODGING WHERE LODGING LIKE M WHERE 子句條件包括一系列值 ORACLE 將通過索引范圍查詢的方式查詢 LODGING PK 由于索引范圍查詢將返回一組值 它的效率就要比索引唯一掃描 低一些 例 2 SELECT LODGING FROM LODGING WHERE MANAGER BILL GATES 這個 SQL 的執行分兩步 LODGING MANAGER 的索引范圍查詢 得到所有符合條件記 錄的 ROWID 和下一步同過 ROWID 訪問表得到 LODGING 列的值 由于 LODGING MANAGER 是一個非唯一性的索引 數據庫不能對它執行索引唯一掃描 由于 SQL 返回 LODGING 列 而它并不存在于 LODGING MANAGER 索引中 所以在索引 范圍查詢后會執行一個通過 ROWID 訪問表的操作 WHERE 子句中 如果索引列所對應的值的第一個字符由通配符 WILDCARD 開始 索 引將不被采用 SELECT LODGING FROM LODGING WHERE MANAGER LIKE HANMAN 在這種情況下 ORACLE 將使用全表掃描 24 24 基礎表的選擇基礎表的選擇 基礎表 Driving Table 是指被最先訪問的表 通常以全表掃描的方式被訪問 根據優化器的不同 SQL 語句中基礎表的選擇是不一樣的 如果你使用的是 CBO COST BASED OPTIMIZER 優化器會檢查 SQL 語句中的每個 表的物理大小 索引的狀態 然后選用花費最低的執行路徑 如果你用 RBO RULE BASED OPTIMIZER 并且所有的連接條件都有索引對應 在這種情況下 基礎表就是 FROM 子句中列在最后的那個表 舉例 SELECT A NAME B MANAGER FROM WORKER A LODGING B WHERE A LODGING B LODING 由于 LODGING 表的 LODING 列上有一個索引 而且 WORKER 表中沒有相比較的索 引 WORKER 表將被作為查詢中的基礎表 25 25 多個平等的索引多個平等的索引 當 SQL 語句的執行路徑可以使用分布在多個表上的多個索引時 ORACLE 會同時 使用多個索引并在運行時對它們的記錄進行合并 檢索出僅對全部索引有效的記錄 在 ORACLE 選擇執行路徑時 唯一性索引的等級高于非唯一性索引 然而這個規 則只有 當 WHERE 子句中索引列和常量比較才有效 如果索引列和其他表的索引類相比較 這 種子句在優化器中的等級是非常低的 如果不同表中兩個想同等級的索引將被引用 FROM 子句中表的順序將決定哪個 會被率先使用 FROM 子句中最后的表的索引將有最高的優先級 如果相同表中兩個想同等級的索引將被引用 WHERE 子句中最先被引用的索引將 有最高的優先級 舉例 DEPTNO 上有一個非唯一性索引 EMP CAT 也有一個非唯一性索引 SELECT ENAME FROM EMP WHERE DEPT NO 20 AND EMP CAT A 這里 DEPTNO 索引將被最先檢索 然后同 EMP CAT 索引檢索出的記錄進行合并 執行路徑如下 TABLE ACCESS BY ROWID ON EMP AND EQUAL INDEX RANGE SCAN ON DEPT IDX INDEX RANGE SCAN ON CAT IDX 26 26 等式比較和范圍比較等式比較和范圍比較 當 WHERE 子句中有索引列 ORACLE 不能合并它們 ORACLE 將用范圍比較 舉例 DEPTNO 上有一個非唯一性索引 EMP CAT 也有一個非唯一性索引 SELECT ENAME FROM EMP WHERE DEPTNO 20 AND EMP CAT A 這里只有 EMP CAT 索引被用到 然后所有的記錄將逐條與 DEPTNO 條件進行比 較 執行路徑如下 TABLE ACCESS BY ROWID ON EMP INDEX RANGE SCAN ON CAT IDX 27 27 不明確的索引等級不明確的索引等級 當 ORACLE 無法判斷索引的等級高低差別 優化器將只使用一個索引 它就是在 WHERE 子句中被列在最前面的 舉例 DEPTNO 上有一個非唯一性索引 EMP CAT 也有一個非唯一性索引 SELECT ENAME FROM EMP WHERE DEPTNO 20 AND EMP CAT A 這里 ORACLE 只用到了 DEPT NO 索引 執行路徑如下 TABLE ACCESS BY ROWID ON EMP INDEX RANGE SCAN ON DEPT IDX 我們來試一下以下這種情況我們來試一下以下這種情況 SQL SQL selectselect index name index name uniquenessuniqueness fromfrom user indexesuser indexes wherewhere table nametable name EMP EMP INDEX NAMEINDEX NAME UNIQUENESUNIQUENES EMPNOEMPNO UNIQUEUNIQUE EMPTYPEEMPTYPE NONUNIQUENONUNIQUE SQL SQL selectselect fromfrom empemp wherewhere empnoempno 2 2 andand emp typeemp type A A nono rowsrows selectedselected ExecutionExecution PlanPlan 0 0 SELECTSELECT STATEMENTSTATEMENT Optimizer CHOOSEOptimizer CHOOSE 1 1 0 0 TABLETABLE ACCESSACCESS BY BY INDEXINDEX ROWID ROWID OFOF EMP EMP 2 2 1 1 INDEXINDEX RANGE RANGE SCAN SCAN OFOF EMPTYPE EMPTYPE NON UNIQUE NON UNIQUE 雖然雖然 EMPNOEMPNO 是唯一性索引是唯一性索引 但是由于它所做的是范圍比較但是由于它所做的是范圍比較 等級要比非唯一性索等級要比非唯一性索 引的等式比較低引的等式比較低 28 28 強制索引失效強制索引失效 如果兩個或以上索引具有相同的等級 你可以強制命令 ORACLE 優化器使用其中的 一個 通過它 檢索出的記錄數量少 舉例 SELECT ENAME FROM EMP WHERE EMPNO 7935 AND DEPTNO 0 10 DEPTNO DEPTNO 上的索引將失效上的索引將失效 AND EMP TYPE A EMP TYPE EMP TYPE 上的索引將失效上的索引將失效 這是一種相當直接的提高查詢效率的辦法 但是你必須謹慎考慮這種策略 一般 來說 只有在你希望單獨優化幾個 SQL 時才能采用它 這里有一個例子關于何時采用這種策略 假設在 EMP 表的 EMP TYPE 列上有一個非唯一性的索引而 EMP CLASS 上沒有索引 SELECT ENAME FROM EMP WHERE EMP TYPE A AND EMP CLASS X 優化器會注意到 EMP TYPE 上的索引并使用它 這是目前唯一的選擇 如果 一 段時間以后 另一個非唯一性建立在 EMP CLASS 上 優化器必須對兩個索引進行選擇 在 通常情況下 優化器將使用兩個索引并在他們的結果集合上執行排序及合并 然而 如果其中一個索引 EMP TYPE 接近于唯一性而另一個索引 EMP CLASS 上有幾千 個重復的值 排序及合并就會成為一種不必要的負擔 在這種情況下 你希望使優化 器屏蔽掉 EMP CLASS 索引 用下面的方案就可以解決問題 SELECT ENAME FROM EMP WHERE EMP TYPE A AND EMP CLASS X 29 29 避免在索引列上使用計算 避免在索引列上使用計算 WHERE 子句中 如果索引列是函數的一部分 優化器將不使用索引而使用全表掃 描 舉例 低效 SELECT FROM DEPT WHERE SAL 12 25000 高效 SELECT FROM DEPT WHERE SAL 25000 12 這是一個非常實用的規則 請務必牢記這是一個非常實用的規則 請務必牢記 30 30 自動選擇索引自動選擇索引 如果表中有兩個以上 包括兩個 索引 其中有一個唯一性索引 而其他是非唯 一性 在這種情況下 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 31 31 避免在索引列上使用避免在索引列上使用 NOTNOT 通常 我們要避免在索引列上使用 NOT NOT 會產生在和在索引列上使用函數 相同的 影響 當 ORACLE 遇到 NOT 他就會停止使用索引轉而執行全表掃描 舉例 低效 這里 不使用索引 SELECT FROM DEPT WHERE DEPT CODE NOT 0 高效 這里 使用了索引 SELECT FROM DEPT WHERE DEPT CODE 0 需要注意的是需要注意的是 在某些時候在某些時候 ORACLEORACLE 優化器會自動將優化器會自動將 NOTNOT 轉化成相對應的關系操作轉化成相對應的關系操作 符符 NOT to to NOT NOT 在這個例子中在這個例子中 作者犯了一些錯誤作者犯了一些錯誤 例子中的低效率例子中的低效率 SQLSQL 是不能被執行的是不能被執行的 我做了一些測試我做了一些測試 SQL SQL selectselect fromfrom empemp wherewhere NOTNOT empnoempno 1 1 nono rowsrows selectedselected ExecutionExecution PlanPlan 0 0 SELECTSELECT STATEMENTSTATEMENT Optimizer CHOOSEOptimizer CHOOSE 1 1 0 0 TABLETABLE ACCESSACCESS BY BY INDEXINDEX ROWID ROWID OFOF EMP EMP 2 2 1 1 INDEXINDEX RANGE RANGE SCAN SCAN OFOF EMPNO EMPNO UNIQUE UNIQUE SQL SQL selectselect fromfrom empemp wherewhere empnoempno 替代替代 如果 DEPTNO 上有一個索引 高效 SELECT FROM EMP WHERE DEPTNO 4 低效 SELECT FROM EMP WHERE DEPTNO 3 兩者的區別在于 前者 DBMS 將直接跳到第一個 DEPT 等于 4 的記錄而后者將 首先定位到 DEPTNO 3 的記錄并且向前掃描到第一個 DEPT 大于 3 的記錄 33 33 用用 UNIONUNION 替換替換 OROR 適用于索引列適用于索引列 通常情況下 用 UNION 替換 WHERE 子句中的 OR 將會起到較好的效果 對索引列 使用 OR 將造成全表掃描 注意 以上規則只針對多個索引列有效 如果有 column 沒有被索引 查詢效率可能會因為你沒有選擇 OR 而降低 在下面的例子中 LOC ID 和 REGION 上都建有索引 高效 SELECT LOC ID LOC DESC REGION FROM LOCATION WHERE LOC ID 10 UNION SELECT LOC ID LOC DESC REGION FROM LOCATION WHERE REGION MELBOURNE 低效 SELECT LOC ID LOC DESC REGION FROM LOCATION WHERE LOC ID 10 OR REGION MELBOURNE 如果你堅持要用 OR 那就需要返回記錄最少的索引列寫在最前面 注意 WHERE KEY1 10 返回最少記錄 OR KEY2 20 返回最多記錄 ORACLE 內部將以上轉換為 WHERE KEY1 10 AND NOT KEY1 10 AND KEY2 20 下面的測試數據僅供參考下面的測試數據僅供參考 a a 10031003 返回一條記錄返回一條記錄 b b 1 1 返回返回 10031003 條記錄條記錄 SQL SQL selectselect fromfrom unionvsorunionvsor 1st 1st test test 2 2 wherewhere a a 10031003 oror b b 1 1 10031003 rowsrows selected selected ExecutionExecution PlanPlan 0 0 SELECTSELECT STATEMENTSTATEMENT Optimizer CHOOSEOptimizer CHOOSE 1 1 0 0 CONCATENATIONCONCATENATION 2 2 1 1 TABLETABLE ACCESSACCESS BY BY INDEXINDEX ROWID ROWID OFOF UNIONVSOR UNIONVSOR 3 3 2 2 INDEXINDEX RANGE RANGE SCAN SCAN OFOF UB UB NON UNIQUE NON UNIQUE 4 4 1 1 TABLETABLE ACCESSACCESS BY BY INDEXINDEX ROWID ROWID OFOF UNIONVSOR UNIONVSOR 5 5 4 4 INDEXINDEX RANGE RANGE SCAN SCAN OFOF UA UA NON UNIQUE NON UNIQUE StatisticsStatistics 0 0 recursiverecursive callscalls 0 0 dbdb blockblock getsgets 144144 consistentconsistent getsgets 0 0 physicalphysical readsreads 0 0 redoredo sizesize 6374963749 bytesbytes sentsent viavia SQL NetSQL Net toto clientclient 77517751 bytesbytes receivedreceived viavia SQL NetSQL Net fromfrom clientclient 6868 SQL NetSQL Net roundtripsroundtrips to fromto from clientclient 0 0 sortssorts memory memory 0 0 sortssorts disk disk 10031003 rowsrows processedprocessed SQL SQL selectselect fromfrom unionvsorunionvsor 2nd 2nd test test 2 2 wherewhere b b 1 1 oror a a 10031003 10031003 rowsrows selected selected ExecutionExecution PlanPlan 0 0 SELECTSELECT STATEMENTSTATEMENT Optimizer CHOOSEOptimizer CHOOSE 1 1 0 0 CONCATENATIONCONCATENATION 2 2 1 1 TABLETABLE ACCESSACCESS BY BY INDEXINDEX ROWID ROWID OFOF UNIONVSOR UNIONVSOR 3 3 2 2 INDEXINDEX RANGE RANGE SCAN SCAN OFOF UA UA NON UNIQUE NON UNIQUE 4 4 1 1 TABLETABLE ACCESSACCESS BY BY INDEXINDEX ROWID ROWID OFOF UNIONVSOR UNIONVSOR 5 5 4 4 INDEXINDEX RANGE RANGE SCAN SCAN OFOF UB UB NON UNIQUE NON UNIQUE StatisticsStatistics 0 0 recursiverecursive callscalls 0 0 dbdb blockblock getsgets 143143 consistentconsistent getsgets 0 0 physicalphysical readsreads 0 0 redoredo sizesize 6374963749 bytesbytes sentsent viavia SQL NetSQL Net toto clientclient 77517751 bytesbytes receivedreceived viavia SQL NetSQL Net fromfr

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經權益所有人同意不得將文件中的內容挪作商業或盈利用途。
  • 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
  • 6. 下載文件中如有侵權或不適當內容,請與我們聯系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論