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