oracle_SQL優(yōu)化.doc_第1頁
oracle_SQL優(yōu)化.doc_第2頁
oracle_SQL優(yōu)化.doc_第3頁
oracle_SQL優(yōu)化.doc_第4頁
oracle_SQL優(yōu)化.doc_第5頁
已閱讀5頁,還剩29頁未讀 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)

文檔簡介

Oracle sql 性能優(yōu)化調(diào)整性能優(yōu)化調(diào)整 1 訪問訪問 Table 的方式的方式 ORACLE 采用兩種訪問表中記錄的方式 a 全表掃描 全表掃描就是順序地訪問表中每條記錄 ORACLE 采用一次讀入多個數(shù)據(jù)塊 database block 的方式優(yōu)化全表掃描 b 通過 ROWID 訪問表 你可以采用基于 ROWID 的訪問方式情況 提高訪問表的效率 ROWID 包含了表中 記錄的物理位置信息 ORACLE 采用索引 INDEX 實現(xiàn)了數(shù)據(jù)和存放數(shù)據(jù)的物理位置 ROWID 之間的聯(lián)系 通常索引提供了快速訪問 ROWID 的方法 因此那些基于索引列的查詢 就可以得到性能上的提高 2 選擇選擇最有效率的表名最有效率的表名順順序序 ORACLE 的解析器按照從右到左的順序處理的解析器按照從右到左的順序處理 FROM 子句中的表名子句中的表名 因此 FROM 子句中寫在 最后的表 基礎(chǔ)表 driving table 將被最先處理 在 FROM 子句中包含多個表的情況下 你必須 選擇記錄條數(shù)最少的表作為基礎(chǔ)表 當(dāng) ORACLE 處理多個表時 會運用排序及合并的方式連 接它們 首先 掃描第一個表 FROM 子句中最后的那個表 并對記錄進行派序 然后掃描第二個 表 FROM 子句中最后第二個表 最后將所有從第二個表中檢索出的記錄與第一個表中合適 記錄進行合并 例如 表 TAB1 16 384 條記錄 表 TAB2 1 條記錄 選擇 TAB2 作為基礎(chǔ)表 最好的方法 select count from tab1 tab2 執(zhí)行時間 0 96 秒 選擇 TAB2 作為基礎(chǔ)表 不佳的方法 select count from tab2 tab1 執(zhí)行時間 26 09 秒 如果有 3 個以上的表連接查詢 那就需要選擇交叉表 intersection table 作為基礎(chǔ)表 交叉表是指 那個被其他表所引用的表 例如 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 子句子句 根據(jù)這個原理 表之間的連接必須寫在其他 WHERE 條件之前 那些可以過濾掉最大數(shù)量記錄的條件必須寫在 WHERE 子句的末尾 例如 低效 執(zhí)行時間 156 3 秒 SELECT FROM EMP E WHERE SAL 50000 AND JOB MANAGER AND 25 SELECT COUNT FROM EMP WHERE MGR E EMPNO 高效 執(zhí)行時間 10 6 秒 SELECT FROM EMP E WHERE 25 50000 AND JOB MANAGER 4 SELECT 子句中避免使用子句中避免使用 當(dāng)你想在 SELECT 子句中列出所有的 COLUMN 時 使用動態(tài) SQL 列引用 是一個方便的 方法 不幸的是 這是一個非常低效的方法 實際上 ORACLE 在解析的過程中 會將 依次轉(zhuǎn) 換成所有的列名 這個工作是通過查詢數(shù)據(jù)字典完成的 這意味著將耗費更多的時間 5 減少訪問數(shù)據(jù)庫的次數(shù)減少訪問數(shù)據(jù)庫的次數(shù) 當(dāng)執(zhí)行每條 SQL 語句時 ORACLE 在內(nèi)部執(zhí)行了許多工作 解析 SQL 語句 估算索引的利 用率 綁定變量 讀數(shù)據(jù)塊等等 由此可見 減少訪問數(shù)據(jù)庫的次數(shù) 就能實際上減少 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 中重新設(shè)置 ARRAYSIZE 參數(shù) 可以增加每次數(shù)據(jù) 庫訪問的檢索數(shù)據(jù)量 建議值為 200 6 使用使用 DECODE 函數(shù)來減少處理時間函數(shù)來減少處理時間 使用 DECODE 函數(shù)可以避免重復(fù)掃描相同記錄或重復(fù)連接相同的表 例如 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 函數(shù)高效地得到相同結(jié)果 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 函數(shù)也可以運用于 GROUP BY 和 ORDER BY 子句中 7 整合簡單整合簡單 無關(guān)聯(lián)的數(shù)據(jù)庫訪問無關(guān)聯(lián)的數(shù)據(jù)庫訪問 如果你有幾個簡單的數(shù)據(jù)庫查詢語句 你可以把它們整合到一個查詢中 即使它們之間沒有關(guān) 系 例如 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 雖然采取這種方法雖然采取這種方法 效率得到提高效率得到提高 但是程序的可讀性大大降低但是程序的可讀性大大降低 所以還是要權(quán)衡之間的利弊所以還是要權(quán)衡之間的利弊 8 刪除重復(fù)記錄刪除重復(fù)記錄 最高效的刪除重復(fù)記錄方法 因為使用了 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 當(dāng)刪除表中的記錄時 在通常情況下 回滾段 rollback segments 用來存放可以被恢復(fù)的信 息 如果你沒有 COMMIT 事務(wù) ORACLE 會將數(shù)據(jù)恢復(fù)到刪除之前的狀態(tài) 準(zhǔn)確地說是恢復(fù)到 執(zhí)行刪除命令之前的狀況 而當(dāng)運用 TRUNCATE 時 回滾段不再存放任何可被恢復(fù)的信息 當(dāng)命令運行后 數(shù)據(jù)不能被 恢復(fù) 因此很少的資源被調(diào)用 執(zhí)行時間也會很短 TRUNCATE 只在刪除全表適用只在刪除全表適用 TRUNCATE 是是 DDL 不是不是 DML 10 盡量多使用盡量多使用 COMMIT 只要有可能 在程序中盡量多使用 COMMIT 這樣程序的性能得到提高 需求也會因為 COMMIT 所釋放的資源而減少 COMMIT 所釋放的資源 a 回滾段上用于恢復(fù)數(shù)據(jù)的信息 b 被程序語句獲得的鎖 c redo log buffer 中的空間 d ORACLE 為管理上述 3 種資源中的內(nèi)部花費 在使用在使用 COMMIT 時必須要注意到事務(wù)的完整性時必須要注意到事務(wù)的完整性 現(xiàn)實中效率和事務(wù)完整性往往是魚和熊掌現(xiàn)實中效率和事務(wù)完整性往往是魚和熊掌 不可得兼不可得兼 11 計算記錄條數(shù)計算記錄條數(shù) 和一般的觀點相反 count 比 count 1 稍快 當(dāng)然如果可以通過索引檢索 對索引列的計 數(shù)仍舊是最快的 例如 COUNT EMPNO 在在 CSDN 論壇中論壇中 曾經(jīng)對此有過相當(dāng)熱烈的討論曾經(jīng)對此有過相當(dāng)熱烈的討論 作者的觀點并不十分準(zhǔn)確作者的觀點并不十分準(zhǔn)確 通過實際的測試通過實際的測試 上上 述三種方法并沒有顯著的性能差別述三種方法并沒有顯著的性能差別 12 用用 Where 子句替換子句替換 HAVING 子句子句 避免使用 HAVING 子句 HAVING 只會在檢索出所有記錄之后才對結(jié)果集進行過濾 這個 處理需要排序 總計等操作 如果能通過 WHERE 子句限制記錄的數(shù)目 那就能減少這方面的開銷 例如 低效 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 中的條件一般用于對一些集合函數(shù)的比較中的條件一般用于對一些集合函數(shù)的比較 如如 COUNT 等等等等 除此而外除此而外 一般的條件一般的條件 應(yīng)該寫在應(yīng)該寫在 WHERE 子句中子句中 Having 用法 用法 數(shù)據(jù)表 student 表結(jié)構(gòu) Field Name DataType Len id int 20 name varchar 25 major varchar 25 score int 20 sex varchar 20 rn 表數(shù)據(jù) 編號 姓名 專業(yè) 學(xué)分 性別 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 現(xiàn)在我們要得到一個視圖 要求查詢性別為男生 并且列出每個學(xué)生的總成績 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 可以看到總共查到有兩組 兩組的學(xué)生分別是 jak 和 leo 每一組都是同一個學(xué)生 這樣我們就 可以使用聚合函數(shù)了 只有使用了 group by 語句 才能使用如 count sum 之類的聚合函數(shù) 下面我們再對上面的結(jié)果做進一步的篩選 只顯示總分?jǐn)?shù)大于 230 的學(xué)生 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 的功能差不多 結(jié)論 1 WHERE 子句用來篩選 FROM 子句中指定的操作所產(chǎn)生的行 2 GROUP BY 子句用來分組 WHERE 子句的輸出 3 HAVING 子句用來從分組的結(jié)果中篩選行 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 通過內(nèi)部函數(shù)提高通過內(nèi)部函數(shù)提高 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 通過調(diào)用下面的函數(shù)可以提高效率 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 經(jīng)常在論壇中看到如經(jīng)常在論壇中看到如 能不能用一個能不能用一個 SQL 寫出寫出 的貼子的貼子 殊不知復(fù)雜的殊不知復(fù)雜的 SQL 往往犧牲了執(zhí)往往犧牲了執(zhí) 行效率行效率 能夠掌握上面的運用函數(shù)解決問題的方法在實際工作中是非常有意義的能夠掌握上面的運用函數(shù)解決問題的方法在實際工作中是非常有意義的 15 使用表的別名使用表的別名 Alias 當(dāng)在 SQL 語句中連接多個表時 請使用表的別名并把別名前綴于每個 Column 上 這樣一來 就可以減少解析的時間并減少那些由 Column 歧義引起的語法錯誤 Column 歧義指的是由于歧義指的是由于 SQL 中不同的表具有相同的中不同的表具有相同的 Column 名名 當(dāng)當(dāng) SQL 語句中出現(xiàn)這個語句中出現(xiàn)這個 Column 時時 SQL 解析器無法判斷這個解析器無法判斷這個 Column 的歸屬的歸屬 16 用用 EXISTS 替代替代 IN 在許多基于基礎(chǔ)表的查詢中 為了滿足一個條件 往往需要對另一個表進行聯(lián)接 在這種情況下 使用 EXISTS 或 NOT EXISTS 通常將提高查詢的效率 低效 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 相對來說相對來說 用用 NOT EXISTS 替換替換 NOT IN 將更顯著地提高效率將更顯著地提高效率 下一節(jié)中將指出下一節(jié)中將指出 17 用用 NOT EXISTS 替代替代 NOT IN 在子查詢中 NOT IN 子句將執(zhí)行一個內(nèi)部的排序和合并 無論在哪種情況下 NOT IN 都是最 低效的 因為它對子查詢中的表執(zhí)行了一個全表遍歷 為了避免使用 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 當(dāng)提交一個包含一對多表信息 比如部門表和雇員表 的查詢時 避免在 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 核心模塊將在子查詢的條件一旦滿足后 立刻返 回結(jié)果 20 識別識別 低效執(zhí)行低效執(zhí)行 的的 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 雖然目前各種關(guān)于雖然目前各種關(guān)于 SQL 優(yōu)化的圖形化工具層出不窮優(yōu)化的圖形化工具層出不窮 但是寫出自己的但是寫出自己的 SQL 工具來解工具來解 決問題始終是一個最好的方法決問題始終是一個最好的方法 21 使用使用 TKPROF 工具來查詢工具來查詢 SQL 性能狀態(tài)性能狀態(tài) SQL trace 工具收集正在執(zhí)行的 SQL 的性能狀態(tài)數(shù)據(jù)并記錄到一個跟蹤文件中 這個跟蹤文件提 供了許多有用的信息 例如解析次數(shù) 執(zhí)行次數(shù) CPU 使用時間等 這些數(shù)據(jù)將可以用來優(yōu)化你的系 統(tǒng) 設(shè)置 SQL TRACE 在會話級別 有效 ALTER SESSION SET SQL TRACE TRUE 設(shè)置 SQL TRACE 在整個數(shù)據(jù)庫有效仿 你必須將 SQL TRACE 參數(shù)在 init ora 中設(shè)為 TRUE USER DUMP DEST 參數(shù)說明了生成跟蹤文件的目錄 作者并沒有提到作者并沒有提到 TKPROF 的用法的用法 對對 SQL TRACE 的用法也不夠準(zhǔn)確的用法也不夠準(zhǔn)確 設(shè)置設(shè)置 SQL TRACE 首首 先要在先要在 init ora 中設(shè)定中設(shè)定 TIMED STATISTICS 這樣才能得到那些重要的時間狀態(tài)這樣才能得到那些重要的時間狀態(tài) 生成的生成的 trace 文件是不可讀的文件是不可讀的 所以要用所以要用 TKPROF 工具對其進行轉(zhuǎn)換工具對其進行轉(zhuǎn)換 TKPROF 有許多執(zhí)行參數(shù)有許多執(zhí)行參數(shù) 大家可以參大家可以參 考考 ORACLE 手冊來了解具體的配置手冊來了解具體的配置 22 22 用索引提高效率用索引提高效率 索引是表的一個概念部分 用來提高檢索數(shù)據(jù)的效率 實際上 ORACLE 使用了一個 復(fù)雜的自平衡 B tree 結(jié)構(gòu) 通常 通過索引查詢數(shù)據(jù)比全表掃描要快 當(dāng) ORACLE 找 出執(zhí)行查詢和 Update 語句的最佳路徑時 ORACLE 優(yōu)化器將使用索引 同樣在聯(lián)結(jié)多 個表時使用索引也可以提高效率 另一個使用索引的好處是 它提供了主鍵 primary key 的唯一性驗證 除了那些 LONG 或 LONG RAW 數(shù)據(jù)類型 你可以索引幾乎所有的列 通常 在大型 表中使用索引特別有效 當(dāng)然 你也會發(fā)現(xiàn) 在掃描小表時 使用索引同樣能提高效 率 雖然使用索引能得到查詢效率的提高 但是我們也必須注意到它的代價 索引需 要空間來 存儲 也需要定期維護 每當(dāng)有記錄在表中增減或索引列被修改時 索引本身也會被 修改 這意味著每條記錄的 INSERT DELETE UPDATE 將為此多付出 4 5 次的磁 盤 I O 因為索引需要額外的存儲空間和處理 那些不必要的索引反而會使查詢反應(yīng) 時間變慢 定期的重構(gòu)索引是有必要的定期的重構(gòu)索引是有必要的 ALTERALTER INDEXINDEX REBUILDREBUILD 23 23 索引的操作索引的操作 ORACLE 對索引有兩種訪問模式 索引唯一掃描 INDEX UNIQUE SCAN 大多數(shù)情況下 優(yōu)化器通過 WHERE 子句訪問 INDEX 例如 表 LODGING 有兩個索引 建立在 LODGING 列上的唯一性索引 LODGING PK 和 建立在 MANAGER 列上的非唯一性索引 LODGING MANAGER SELECT FROM LODGING WHERE LODGING ROSE HILL 在內(nèi)部 上述 SQL 將被分成兩步執(zhí)行 首先 LODGING PK 索引將通過索引唯 一掃描的方式被訪問 獲得相對應(yīng)的 ROWID 通過 ROWID 訪問表的方式 執(zhí)行下一步 檢索 如果被檢索返回的列包括在 INDEX 列中 ORACLE 將不執(zhí)行第二步的處理 通過 ROWID 訪問表 因為檢索數(shù)據(jù)保存在索引中 單單訪問索引就可以完全滿足查詢結(jié) 果 下面 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 的執(zhí)行分兩步 LODGING MANAGER 的索引范圍查詢 得到所有符合條件記 錄的 ROWID 和下一步同過 ROWID 訪問表得到 LODGING 列的值 由于 LODGING MANAGER 是一個非唯一性的索引 數(shù)據(jù)庫不能對它執(zhí)行索引唯一掃描 由于 SQL 返回 LODGING 列 而它并不存在于 LODGING MANAGER 索引中 所以在索引 范圍查詢后會執(zhí)行一個通過 ROWID 訪問表的操作 WHERE 子句中 如果索引列所對應(yīng)的值的第一個字符由通配符 WILDCARD 開始 索 引將不被采用 SELECT LODGING FROM LODGING WHERE MANAGER LIKE HANMAN 在這種情況下 ORACLE 將使用全表掃描 24 24 基礎(chǔ)表的選擇基礎(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 子句中列在最后的那個表 舉例 SELECT A NAME B MANAGER FROM WORKER A LODGING B WHERE A LODGING B LODING 由于 LODGING 表的 LODING 列上有一個索引 而且 WORKER 表中沒有相比較的索 引 WORKER 表將被作為查詢中的基礎(chǔ)表 25 25 多個平等的索引多個平等的索引 當(dāng) SQL 語句的執(zhí)行路徑可以使用分布在多個表上的多個索引時 ORACLE 會同時 使用多個索引并在運行時對它們的記錄進行合并 檢索出僅對全部索引有效的記錄 在 ORACLE 選擇執(zhí)行路徑時 唯一性索引的等級高于非唯一性索引 然而這個規(guī) 則只有 當(dāng) WHERE 子句中索引列和常量比較才有效 如果索引列和其他表的索引類相比較 這 種子句在優(yōu)化器中的等級是非常低的 如果不同表中兩個想同等級的索引將被引用 FROM 子句中表的順序?qū)Q定哪個 會被率先使用 FROM 子句中最后的表的索引將有最高的優(yōu)先級 如果相同表中兩個想同等級的索引將被引用 WHERE 子句中最先被引用的索引將 有最高的優(yōu)先級 舉例 DEPTNO 上有一個非唯一性索引 EMP CAT 也有一個非唯一性索引 SELECT ENAME FROM EMP WHERE DEPT NO 20 AND EMP CAT A 這里 DEPTNO 索引將被最先檢索 然后同 EMP CAT 索引檢索出的記錄進行合并 執(zhí)行路徑如下 TABLE ACCESS BY ROWID ON EMP AND EQUAL INDEX RANGE SCAN ON DEPT IDX INDEX RANGE SCAN ON CAT IDX 26 26 等式比較和范圍比較等式比較和范圍比較 當(dāng) WHERE 子句中有索引列 ORACLE 不能合并它們 ORACLE 將用范圍比較 舉例 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 27 27 不明確的索引等級不明確的索引等級 當(dāng) 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 我們來試一下以下這種情況我們來試一下以下這種情況 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 優(yōu)化器使用其中的 一個 通過它 檢索出的記錄數(shù)量少 舉例 SELECT ENAME FROM EMP WHERE EMPNO 7935 AND DEPTNO 0 10 DEPTNO DEPTNO 上的索引將失效上的索引將失效 AND EMP TYPE A EMP TYPE EMP TYPE 上的索引將失效上的索引將失效 這是一種相當(dāng)直接的提高查詢效率的辦法 但是你必須謹(jǐn)慎考慮這種策略 一般 來說 只有在你希望單獨優(yōu)化幾個 SQL 時才能采用它 這里有一個例子關(guān)于何時采用這種策略 假設(shè)在 EMP 表的 EMP TYPE 列上有一個非唯一性的索引而 EMP CLASS 上沒有索引 SELECT ENAME FROM EMP WHERE EMP TYPE A AND EMP CLASS X 優(yōu)化器會注意到 EMP TYPE 上的索引并使用它 這是目前唯一的選擇 如果 一 段時間以后 另一個非唯一性建立在 EMP CLASS 上 優(yōu)化器必須對兩個索引進行選擇 在 通常情況下 優(yōu)化器將使用兩個索引并在他們的結(jié)果集合上執(zhí)行排序及合并 然而 如果其中一個索引 EMP TYPE 接近于唯一性而另一個索引 EMP CLASS 上有幾千 個重復(fù)的值 排序及合并就會成為一種不必要的負擔(dān) 在這種情況下 你希望使優(yōu)化 器屏蔽掉 EMP CLASS 索引 用下面的方案就可以解決問題 SELECT ENAME FROM EMP WHERE EMP TYPE A AND EMP CLASS X 29 29 避免在索引列上使用計算 避免在索引列上使用計算 WHERE 子句中 如果索引列是函數(shù)的一部分 優(yōu)化器將不使用索引而使用全表掃 描 舉例 低效 SELECT FROM DEPT WHERE SAL 12 25000 高效 SELECT FROM DEPT WHERE SAL 25000 12 這是一個非常實用的規(guī)則 請務(wù)必牢記這是一個非常實用的規(guī)則 請務(wù)必牢記 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 會產(chǎn)生在和在索引列上使用函數(shù) 相同的 影響 當(dāng) ORACLE 遇到 NOT 他就會停止使用索引轉(zhuǎn)而執(zhí)行全表掃描 舉例 低效 這里 不使用索引 SELECT FROM DEPT WHERE DEPT CODE NOT 0 高效 這里 使用了索引 SELECT FROM DEPT WHERE DEPT CODE 0 需要注意的是需要注意的是 在某些時候在某些時候 ORACLEORACLE 優(yōu)化器會自動將優(yōu)化器會自動將 NOTNOT 轉(zhuǎn)化成相對應(yīng)的關(guān)系操作轉(zhuǎn)化成相對應(yīng)的關(guān)系操作 符符 NOT to to NOT NOT 在這個例子中在這個例子中 作者犯了一些錯誤作者犯了一些錯誤 例子中的低效率例子中的低效率 SQLSQL 是不能被執(zhí)行的是不能被執(zhí)行的 我做了一些測試我做了一些測試 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 兩者的區(qū)別在于 前者 DBMS 將直接跳到第一個 DEPT 等于 4 的記錄而后者將 首先定位到 DEPTNO 3 的記錄并且向前掃描到第一個 DEPT 大于 3 的記錄 33 33 用用 UNIONUNION 替換替換 OROR 適用于索引列適用于索引列 通常情況下 用 UNION 替換 WHERE 子句中的 OR 將會起到較好的效果 對索引列 使用 OR 將造成全表掃描 注意 以上規(guī)則只針對多個索引列有效 如果有 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 內(nèi)部將以上轉(zhuǎn)換為 WHERE KEY1 10 AND NOT KEY1 10 AND KEY2 20 下面的測試數(shù)據(jù)僅供參考下面的測試數(shù)據(jù)僅供參考 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. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論