13 笛卡爾積(CARTESIAN)--優化主題系列

提問笛卡爾積平時工作遇到的多嗎??什麼情況下會發生笛卡爾積??

笛卡爾積JOIN性能一定很差嗎??有沒有性能很好的時候??

JOIN條件的時候會不會發生笛卡爾積??

 

笛卡爾積(CartesianJoin)

 

當一個SQL中兩個表無關聯條件,或者關聯條件可以被忽略的時候就會發生笛卡爾積。遇到這種情況要仔細分析SQL是否符合需求,是不是SQL寫錯了。在有些情況下,如果CBO預估兩個表返回的行數很少(通常小於10),那麼也可能發生笛卡爾積。遇到這樣的情況:

1.如果SQL跑得很快,並且兩個表返回的真實行數確實很少,那麼走笛卡爾積可能是最優化

  的,這個時候我們不用管。只要是SQL跑得快我們都不用管。

2.統計信息不準確導致CBO錯誤估算,從而引發笛卡爾積連接。這時要更新統計信息。

3.CBO計算返回行數錯誤,導致笛卡爾積。CBO計算返回行數錯誤經常發生,因爲CBO是基

  於一些數學公式計算的,出錯很正常。這個時候我們可以用HINT更正執行計劃。

 

在做SQL優化的時候,要注意MERGEJOIN CARTESIAN關鍵字,一旦發現有笛卡爾積仔細分析到底是哪些原因引發的

 

小例子如下:

explain plan for SELECT b.agmt_id,

              b.corp_org,

              b.cur_cd,

              b.businesstype,

              c.object_no,

              c.guaranty_crsum,

              row_number() over(PARTITION BY b.agmt_id, b.corp_org, c.object_no ORDER BYb.agmt_id, b.corp_org, c.object_no) row_no

          FROMb_m_business_contract         b,

              dwf.f_contract_relative       c,

              dwf.f_agt_guaranty_relative_h r,

              dwf.f_agt_guaranty_info_h     g

         WHEREb.corp_org = c.corp_org

           ANDb.agmt_id = c.contract_seqno

           ANDc.object_type = 'GuarantyContract'

           ANDr.start_dt <= DATE'2012-12-12'

           ANDr.end_dt > DATE'2012-12-12'

           ANDc.contract_seqno = r.object_no

           ANDc.object_no = r.guaranty_no

           ANDc.corp_org = r.corp_org

           ANDr.object_type = 'BusinessContract'

           ANDr.agmt_id = g.agmt_id

           ANDr.corp_org = g.corp_org

           ANDg.start_dt <= DATE'2012-12-12'

           ANDg.end_dt > DATE'2012-12-12'

         ANDg.guarantytype = '121212'


看到這個執行計劃,第一眼就知道是B_M_BUSINESS_CONTRACT表出問題了,請看我分析步驟:

1.ID=6這步是全表掃描,並且沒過濾條件(因爲沒有*)

2.CBO認爲它只返回1行。你自己想想,全表掃描返回1行,並且無過濾條件,這個可能嗎,

  難道表裏面真的就只有1行數據?這不符合常識,那麼顯然是它統計信息有問題。

3.根據前面提到的知識,如果返回的行數真的很少,那麼走笛卡爾積它反而更快。

 

這些因素最終導致了走笛卡爾積。

當然了,你也可以手工的select count(*) from B_M_BUSINESS_CONTRACT;

查看返回數據,當你看到返回幾千上萬條,那麼你也知道它統計信息有問題。

 

我們假設這個表1000條數據這個很可能吧??

是不是總的結果放大了1000倍??後果是什麼??

是不是導致了NL的被驅動表很無辜的被掃描了 1000次??

所以這個SQL比之前很可能慢1000

如果真的返回1條結果那麼執行計劃就是對的因爲沒有進行數據的放大

看到MERGEJOIN CARTESIAN關鍵字要看關鍵字下面的返回記錄數

ID=5 這個是笛卡爾積的關鍵字也就是ID=6count一把看返回行數是不是1

超過1行基本上就是錯誤的只需要管理他最近的即可

無論是NL還是笛卡爾積都直管離它最近的即可

要防止I/O爆炸式增長

SQL優化的核心思想是什麼??減少I/O


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章