1.笛卡爾積定義
笛卡爾積在SQL中的實現方式既是交叉連接(Cross Join)。所有連接方式都會先生成臨時笛卡爾積表,笛卡爾積是關系代數里的一個概念,表示兩個表中的每一行數據任意組合,上圖中兩個表連接即為笛卡爾積(交叉連接)
在實際應用中,笛卡爾積本身大多沒有什么實際用處,只有在兩個表連接時加上限制條件,才會有實際意義,下面看內連接
示例:
l表
lid name
----------- --------------------
101 北京
102 太原
101 NULL
102 NULL
matid qty lid mname
----------- ----------- ----------- --------------------
10011 1 101 北京
20012 1 102 太原
10011 1 102 太原
10011 1 102 太原
lm:
lid name matid qty lid mname
----------- -------------------- ----------- ----------- ----------- --------------------
101 北京 10011 1 101 北京
102 太原 10011 1 101 北京
101 NULL 10011 1 101 北京
102 NULL 10011 1 101 北京
101 北京 20012 1 102 太原
102 太原 20012 1 102 太原
101 NULL 20012 1 102 太原
102 NULL 20012 1 102 太原
101 北京 10011 1 102 太原
102 太原 10011 1 102 太原
101 NULL 10011 1 102 太原
102 NULL 10011 1 102 太原
101 北京 10011 1 102 太原
102 太原 10011 1 102 太原
101 NULL 10011 1 102 太原
102 NULL 10011 1 102 太原
(16 行受影響)
2.笛卡爾積產生原因
- 表連接缺少關聯條件,這個是必須要改的;
- 表連接有關聯條件,但是oracle判斷用笛卡爾積更快,也會出現笛卡爾積,這個時候要看實際執行速度;oracle這樣判斷,一般是表比較小,這個時候要特別檢查表的數據量是不是真的很少,以免oracle因為統計信息錯誤而誤判
3.產生笛卡爾積的解決方案
- 針對 接缺少關聯條件導致的笛卡爾積,一般業務是不會直接這么操作的,如果SQL是這樣的需要查看SQL是否正確。
- 針對有關聯條件, oracle仍然采用了笛卡爾積的方式 有兩種情況
由於ORACLE判斷作笛卡爾積,說明兩表關聯,至少有一張表是小表,查看執行計划的基數 這個指數如果與實際相同,則建議不作優化修改即可。
如果查看執行計划的基數與實際基數不同,則由可能是oracle數據誤判表的基數,則可采用hint方式,改變SQL的執行過程。
示例如下:
select /*+cardinality(ds, 1000) */ re.usercode "userCode",
re.referrername "userName",
re.referrertel "userPhone",
re.we_chat_id "userWeChat",
decode(re.referrerlevel, 'L3', 'SCR', 'CR') "refLevel"
from l_ds_white_mas ds, l_referrer_mas re, l_ds_white_referrer_rel rel
where rel.usercode = re.usercode
and ds.dsUm = rel.dsUm
and ds.status = 1
and rel.is_effect = 1
and re.iseffective = '1'
and re.status = 1
and re.usercode = :1