ORA-01795,in和exists性能
今天,客戶那邊出來一個問題,出現(xiàn)"ORA-01795:列表中的最大表達式數(shù)為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')
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')
調(diào)查后發(fā)現(xiàn),在"PLSQL Developer"和"sqldeveloper"中直接運行時,都不會報錯,雖然上面子查詢的記錄大于1000條。
然后,嘗試將子查詢改成拼接一個大于1000項的數(shù)組,結(jié)果如愿出現(xiàn)"ORA-01795"異常。
猜想,開發(fā)這邊的數(shù)據(jù)庫可能將上述sql文優(yōu)化了,但客戶數(shù)據(jù)庫沒有經(jīng)編譯器優(yōu)化,所以出異常。
可能優(yōu)化成了以下的形式:
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'
2 where e1.VIPNO = e2.EMPNO;
2 and e1.GROUP_ID = '0001'
2 and e1.SUBGROUP_ID = '000101'
最終,個人修改意見是,修改成兩張表鏈結(jié)的形式,即優(yōu)化以后的樣子。這樣修改,性能先不管,至少不會出現(xiàn)異常。
還有個尾巴留下來了,就是In的性能問題。現(xiàn)將網(wǎng)上查到的東西貼出來。
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)
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系統(tǒng)在執(zhí)行IN子查詢時,首先執(zhí)行 子查詢,并將獲得的結(jié)果列表存放在在一個加了索引的臨時表中。在執(zhí)行子查詢之前,系統(tǒng)先將主查詢掛起,待子查詢執(zhí)行完畢,存放在臨時表中以后再執(zhí)行主查 詢。
用第二種:通過使用 EXIST,Oracle系統(tǒng)會首先檢查主查詢,然后運行子查詢直到它找到第一個匹配項,這就節(jié)省了時間。這也就是使用EXISTS比使用IN通常查詢速度快的原因。子查詢以‘select 'X'開始。運用EXISTS子句不管子查詢從表中抽取什么數(shù)據(jù)它只查看where子句。這樣優(yōu)化器就不必遍歷整個表而僅根據(jù)索引就可完成工作(這里假定 在where語句中使用的列存在索引)。
相對于IN子句來說,EXISTS使用相連子查詢,構(gòu)造起來要比IN子查詢困難一些。
比較一致的看法是:為了確定在基于規(guī)則的最優(yōu)化中,哪一種子句性能更佳,不妨考慮一下,與外部查詢相比,內(nèi)部查詢會返回多少行記錄。許多情況下,EXISTS的表現(xiàn)更突出, 這是因為,它需要你指定一個加入條件,這就可以調(diào)用一個INDEX掃描。盡管如此,如果該查詢的結(jié)果很小的話,IN常常表現(xiàn)得更好。你通常都愿意運行那些 能首先返回較少的結(jié)果的查詢。
千言萬語總結(jié)成一句話:如果內(nèi)表大,外表小用exists或not exists,反之用in或not in;
個人推薦還是用兩張表鏈結(jié)的形式,直觀簡單,至少不會出現(xiàn)ORA-01795異常
posted on 2009-09-07 13:54 游雯 閱讀(4959) 評論(0) 編輯 收藏 所屬分類: Java技術(shù)