有個空間

          有個標題

          ORA-01795,in和exists性能

          今天,客戶那邊出來一個問題,出現"ORA-01795:列表中的最大表達式數為1000 "異常。

          sql文是這樣的:
          1 select ENAME
          2   from  VIP_EMP
          3  where GROUP_ID = '0001'
          4    and SUBGROUP_ID = '000101'
          5    and VIPNO  in
          6        (select EMPNO
          7           from EMP
          8          where EMPTYPE = 'VIP')

          調查后發現,在"PLSQL Developer"和"sqldeveloper"中直接運行時,都不會報錯,雖然上面子查詢的記錄大于1000條。
          然后,嘗試將子查詢改成拼接一個大于1000項的數組,結果如愿出現"ORA-01795"異常。
          猜想,開發這邊的數據庫可能將上述sql文優化了,但客戶數據庫沒有經編譯器優化,所以出異常。

          可能優化成了以下的形式:
          1 select e1.ENAME from VIP_EMP e1, (select EMPNO from EMP where EMPTYPE= 'VIP') e2 
          2    where e1.VIPNO = e2.EMPNO;
          2        and e1.GROUP_ID = '0001'
          2        and e1.SUBGROUP_ID = '000101'

          最終,個人修改意見是,修改成兩張表鏈結的形式,即優化以后的樣子。這樣修改,性能先不管,至少不會出現異常。

          還有個尾巴留下來了,就是In的性能問題。現將網上查到的東西貼出來。

          1.in和exists的性能差別

           在where子句中可以使用兩種格式的子查詢。

          第一種格式是使用IN操作符,第二種格式是使用EXIST操作符。

          修改的exists形式:

          1  select e1.ENAME
          2    from VIP_EMP e1
          3   where e1.GROUP_ID = '0001'
          4     and e1.SUBGROUP_ID = '000101'
          5     and exists (select 0
          6            from EMP e2
          7           where e2.EMPTYPE = 'VIP'
          8             and e2.EMPNO = e1.VIPNO)

          用第一種:Oracle系統在執行IN子查詢時,首先執行 子查詢,并將獲得的結果列表存放在在一個加了索引的臨時表中。在執行子查詢之前,系統先將主查詢掛起,待子查詢執行完畢,存放在臨時表中以后再執行主查 詢。

          用第二種:通過使用 EXIST,Oracle系統會首先檢查主查詢,然后運行子查詢直到它找到第一個匹配項,這就節省了時間。這也就是使用EXISTS比使用IN通常查詢速度快的原因。子查詢以‘select 'X'開始。運用EXISTS子句不管子查詢從表中抽取什么數據它只查看where子句。這樣優化器就不必遍歷整個表而僅根據索引就可完成工作(這里假定 在where語句中使用的列存在索引)。

          相對于IN子句來說,EXISTS使用相連子查詢,構造起來要比IN子查詢困難一些。


          同時應盡可能使用NOT EXISTS來代替NOT IN,盡管二者都使用了NOT(不能使用索引而降低速度),NOT EXISTS要比NOT IN查詢效率更高。

          比較一致的看法是:為了確定在基于規則的最優化中,哪一種子句性能更佳,不妨考慮一下,與外部查詢相比,內部查詢會返回多少行記錄。許多情況下,EXISTS的表現更突出, 這是因為,它需要你指定一個加入條件,這就可以調用一個INDEX掃描。盡管如此,如果該查詢的結果很小的話,IN常常表現得更好。你通常都愿意運行那些 能首先返回較少的結果的查詢。

          千言萬語總結成一句話:如果內表大,外表小用exists或not exists,反之用in或not in;

          個人推薦還是用兩張表鏈結的形式,直觀簡單,至少不會出現ORA-01795異常


          posted on 2009-09-07 13:54 游雯 閱讀(4959) 評論(0)  編輯  收藏 所屬分類: Java技術

          主站蜘蛛池模板: 台东市| 罗山县| 仁寿县| 阿瓦提县| 景宁| 宁乡县| 苏尼特左旗| 育儿| 肥东县| 昭觉县| 阿拉善盟| 汶川县| 大荔县| 察雅县| 乌审旗| 东辽县| 安徽省| 武清区| 喀喇| 中江县| 明水县| 东安县| 临颍县| 河西区| 中超| 班戈县| 通州市| 霸州市| 嘉黎县| 泰顺县| 垣曲县| 钟祥市| 阿鲁科尔沁旗| 巴楚县| 汉川市| 杂多县| 桐城市| 确山县| 祁连县| 泽普县| 边坝县|