當(dāng)前位置:首頁 > IT技術(shù) > 數(shù)據(jù)庫 > 正文

Oracle分析函數(shù)和exists/not exists命中注定相克啊
2022-05-31 17:09:31

?

Oracle分析函數(shù)和exists/not exists命中注定相克啊

?

舉個(gè)栗子,有如下SQL:

select h.c1, h.c2, h.c3, h.c4, b.c5
  from h, b
 where h.c1 = b.c1
   and not exists
 (select 1
          from child cs
         where cs.old_c3 = h.c3
           and cs.old_c4 = h.c4
           and cs.c5 = b.c5
           and cs.create_time = (select max(t.create_time)
                                   from child t
                                  where t.old_c3 = h.c3
                                    and t.old_c4 = h.c4
                                    and t.c5 = b.c5));

這條SQL中,exists后邊的子查詢中,child表使用了兩次,若是關(guān)聯(lián)條件沒有索引或者有索引但是用不上導(dǎo)致的child全表掃,就會(huì)有兩次全表掃描。

child表如果很大的話是無法忍受兩次的全表掃,極大的延遲SQL的執(zhí)行時(shí)間并且消耗大量IO。

可以利用分析函數(shù)將SQL改成如下:

select h.c1, h.c2, h.c3, h.c4, b.c5
  from h, b
 where h.c1 = b.c1
   and not exists (select 1
          from (select 1,
                       rank() over(partition by cs.old_c3, cs.old_c4, cs.c5 order by cs.create_time desc) rk
                  from child cs
                 where cs.old_c3 = h.c3
                   and cs.old_c4 = h.c4
                   and cs.c5 = b.c5)
         where rk = 1);

這兩條SQL完全等價(jià),并且更改后的child表只會(huì)掃描一次。

但是?。?!

更改后的SQL是無法成功執(zhí)行的,因?yàn)閮蓪幼硬樵儠?huì)導(dǎo)致h表,b表無法被最里層的查詢認(rèn)到。

執(zhí)行會(huì)報(bào)錯(cuò):

ORA-00904: "B"."C5": invalid identifier

這個(gè)問題網(wǎng)上也有人有類似的:https://blog.csdn.net/weixin_28950015/article/details/116386137

?

沒辦法了,用了分析函數(shù)就注定要套多一層子查詢?nèi)缓髮k放在外邊過濾(總不能用了分析函數(shù)然后不過濾數(shù)據(jù)吧?),這樣在用exists/not exists就勢必會(huì)產(chǎn)生兩層子查詢。。

所以分析函數(shù)和exists/not exists命中注定相克啊。

?

或者有哪個(gè)大佬有啥好的解決替代方案,求賜教。

本文摘自 :https://www.cnblogs.com/

開通會(huì)員,享受整站包年服務(wù)立即開通 >