提問笛卡爾積平時工作遇到的多嗎??什麼情況下會發生笛卡爾積??
笛卡爾積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