<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    Java,J2EE,Weblogic,Oracle

    java項目隨筆
    隨筆 - 90, 文章 - 6, 評論 - 61, 引用 - 0
    數據加載中……

    oracle 優化

    一、用索引提高效率
            索引是表的一個概念部分,用來提高檢索數據的效率,通過索引查詢數據比全表掃描要快.
            ①避免在索引列上使用NOT 通常, 
          我們要避免在索引列上使用NOT, NOT會產生在和在索引列上使用函數相同的影響. ORACLE”遇到”NOT,他就會停止使用索引轉而執行全表掃描
          避免在索引列上使用計算.
    WHERE
    子句中,如果索引列是函數的一部分.優化器將不使用索引而使用全表掃描.
    舉例:
    低效:
    SELECT … FROM  DEPT  WHERE SAL * 12 > 25000;
    高效:
    SELECT … FROM DEPT WHERE SAL > 25000/12;

       ③ 用> 替代 >=
        高效:
    SELECT * FROM  EMP  WHERE  DEPTNO >=4
    低效:
    SELECT * FROM EMP WHERE DEPTNO >3
          ④UNION替換OR (適用于索引列)
    通常情況下, 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, 那就需要返回記錄最少的索引列寫在最前面.

          ⑤避免在索引列上使用IS NULL和IS NOT NULL
    避免在索引中使用任何可以為空的列,ORACLE將無法使用該索引.對于單列索引,如果列包含空值,索引中將不存在此記錄. 對于復合索引,如果每個列都為空,索引中同樣不存在此記錄. 如果至少有一個列不為空,則記錄存在于索引中.舉例: 如果唯一性索引建立在表的A列和B列上, 并且表中存在一條記錄的A,B值為(123,null) , ORACLE將不接受下一條具有相同A,B值(123,null)的記錄(插入). 然而如果所有的索引列都為空,ORACLE將認為整個鍵值為空而空不等于空. 因此你可以插入1000 條具有相同鍵值的記錄,當然它們都是空! 因為空值不存在于索引列中,所以WHERE子句中對索引列進行空值比較將使ORACLE停用該索引.
    低效: (索引失效)
    SELECT … FROM  DEPARTMENT  WHERE  DEPT_CODE IS NOT NULL;
    高效: (索引有效)
    SELECT … FROM  DEPARTMENT  WHERE  DEPT_CODE >=0;

        ⑥總是使用索引的第一個列:
    如果索引是建立在多個列上, 只有在它的第一個列(leading column)where子句引用時,優化器才會選擇使用該索引. 這也是一條簡單而重要的規則,當僅引用索引的第二個列時,優化器使用了全表掃描而忽略了索引

        ⑦ 避免改變索引列的類型.:
    當比較不同數據類型的數據時, ORACLE自動對列進行簡單的類型轉換.
    假設 EMPNO是一個數值類型的索引列.
    SELECT …  FROM EMP  WHERE  EMPNO = ‘123'
    實際上,經過ORACLE類型轉換, 語句轉化為:
    SELECT …  FROM EMP  WHERE  EMPNO = TO_NUMBER(‘123')
    幸運的是,類型轉換沒有發生在索引列上,索引的用途沒有被改變.
    現在,假設EMP_TYPE是一個字符類型的索引列.
    SELECT …  FROM EMP  WHERE EMP_TYPE = 123
    這個語句被ORACLE轉換為:
    SELECT …  FROM EMP  WHERETO_NUMBER(EMP_TYPE)=123
    因為內部發生的類型轉換, 這個索引將不會被用到! 為了避免ORACLE對你的SQL進行隱式的類型轉換, 最好把類型轉換用顯式表現出來. 注意當字符和數值比較時, ORACLE會優先轉換數值類型到字符類型
              
     


    二、選擇最有效率的表名順序(只在基于規則的優化器中有效)
          ORACLE的解析器按照從右到左的順序處理FROM子句中的表名,因此FROM子句中寫在最后的表(基礎表 driving table)將被最先處理.
          例如:

    表 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 

         

    三、  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 < (SELECT COUNT(*) FROM EMP

    WHERE MGR=E.EMPNO)

    AND SAL > 50000

    AND JOB = ‘MANAGER'; 

    四、 優化GROUP BY: 
     

    提高GROUP BY 語句的效率, 可以通過將不需要的記錄在GROUP BY 之前過濾掉.下面兩個查詢返回相同結果但第二個明顯就快了許多.
    低效:
    SELECT JOB , AVG(SAL)
    FROM EMP
    GROUP JOB
    HAVING JOB = ‘PRESIDENT'
    OR JOB = ‘MANAGER'
    高效:
    SELECT JOB , AVG(SAL)
    FROM EMP
    WHERE JOB = ‘PRESIDENT'
    OR JOB = ‘MANAGER'
    GROUP JOB


    五、Where子句替換HAVING子句:
    避免使用HAVING子句, HAVING 只會在檢索出所有記錄之后才對結果集進行過濾. 這個處理需要排序,總計等操作. 如果能通過WHERE子句限制記錄的數目,那就能減少這方面的開銷.



    六、EXISTS替換DISTINCT
    當提交一個包含一對多表信息(比如部門表和雇員表)的查詢時,避免在SELECT子句中使用DISTINCT. 一般可以考慮用EXIST替換, EXISTS 使查詢更為迅速,因為RDBMS核心模塊將在子查詢的條件一旦滿足后,立刻返回結果. 例子:
           (低效):
    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替代IN、用NOT EXISTS替代NOT IN 
    在許多基于基礎表的查詢中,為了滿足一個條件,往往需要對另一個表進行聯接.在這種情況下, 使用EXISTS(或NOT EXISTS)通常將提高查詢的效率. 在子查詢中,NOT IN子句將執行一個內部的排序和合并. 無論在哪種情況下,NOT IN都是最低效的 (因為它對子查詢中的表執行了一個全表遍歷). 為了避免使用NOT IN ,我們可以把它改寫成外連接(Outer Joins)或NOT EXISTS.
    例子:
    (高效)SELECT * FROM  EMP (基礎表)  WHERE  EMPNO > 0  AND  EXISTS (SELECT ‘X'  FROM DEPT  WHERE  DEPT.DEPTNO = EMP.DEPTNO  AND  LOC = ‘MELB')
    (低效)SELECT  * FROM  EMP (基礎表)  WHERE  EMPNO > 0  AND  DEPTNO IN(SELECT DEPTNO  FROM  DEPT  WHERE  LOC = ‘MELB') 





          

    posted on 2008-05-31 13:29 龔椿深 閱讀(378) 評論(0)  編輯  收藏


    只有注冊用戶登錄后才能發表評論。


    網站導航:
     
    主站蜘蛛池模板: 亚洲av永久无码精品表情包| 岛国大片免费在线观看| 久久久无码精品亚洲日韩软件 | 免费日本黄色网址| 亚洲AV日韩AV无码污污网站| 国产成人高清精品免费软件| 亚洲AV成人无码网天堂| 五月天婷亚洲天综合网精品偷| 高潮毛片无遮挡高清免费| 亚洲精品无码久久毛片| 中文字幕无码免费久久9一区9| 亚洲精品高清无码视频| 久久免费看少妇高潮V片特黄| 亚洲精品中文字幕麻豆| 最近2019中文字幕免费看最新| 亚洲爆乳AAA无码专区| 国产精品亚洲mnbav网站| 国产成人免费ā片在线观看老同学| 亚洲午夜精品久久久久久人妖| 久久国内免费视频| 日本亚洲中午字幕乱码| 亚洲最大av无码网址| 无码精品国产一区二区三区免费 | 亚洲国产中文字幕在线观看| 99久久免费国产精品热| 亚洲国产精品午夜电影| 在线观看91精品国产不卡免费| www在线观看免费视频| 久久久无码精品亚洲日韩京东传媒| 一个人免费高清在线观看| 美女黄频视频大全免费的| 日本红怡院亚洲红怡院最新| 免费国产成人高清在线观看网站| 国产成人亚洲精品91专区高清| 久久青青成人亚洲精品| 免费观看大片毛片| 国产免费一区二区视频| 亚洲色大成网站www永久男同| 亚洲一区二区女搞男| 思思99re66在线精品免费观看| 精品一区二区三区免费视频|