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

下載本文檔

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

文檔簡(jiǎn)介

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

最新文檔

評(píng)論

0/150

提交評(píng)論