上QQ阅读APP看书,第一时间看更新
1.6 表与表之间关系
关系型数据库中,表与表之间会进行关联,在进行关联的时候,我们一定要理清楚表与表之间的关系。表与表之间存在3种关系。一种是1∶1关系,一种是1∶N关系,最后一种是N∶N关系。搞懂表与表之间关系,对于SQL优化、SQL等价改写、表设计优化以及分表分库都有巨大帮助。
两表在进行关联的时候,如果两表属于1∶1关系,关联之后返回的结果也是属于1的关系,数据不会重复。如果两表属于1∶N关系,关联之后返回的结果集属于N的关系。如果两表属于N∶N关系,关联之后返回的结果集会产生局部范围的笛卡儿积,N∶N关系一般不存在内/外连接中,只能存在于半连接或者反连接中。
如果我们不知道业务,不知道数据字典,怎么判断两表是什么关系呢?我们以下面SQL为例子。
select * from emp e, dept d where e.deptno = d.deptno;
我们只需要对两表关联列进行汇总统计就能知道两表是什么关系。
SQL> select deptno, count(*) from emp group by deptno order by 2 desc; DEPTNO COUNT(*) ---------- ---------- 30 6 20 5 10 3 SQL> select deptno, count(*) from dept group by deptno order by 2 desc; DEPTNO COUNT(*) ---------- ---------- 10 1 40 1 30 1 20 1
从上面查询我们可以知道两表emp与dept是N∶1关系。搞清楚表与表之间关系对于SQL优化很有帮助。
2013年,我们曾遇到一个案例,SQL运行了12秒,SQL文本如下。
select count(*) from a left join b on a.id=b.id;
案例中a与b是1∶1关系,a与b都是上千万数据量。因为a与b是使用外连接进行关联,不管a与b是否关联上,始终都会返回a的数据,SQL语句中求的是两表关联后的总行数,因为两表是1∶1关系,关联之后数据不会翻番,那么该SQL等价于如下文本。
select count(*) from a;
我们将SQL改写之后,查询可以秒出。如果a与b是n∶1关系,我们也可以将b表去掉,因为两表关联之后数据不会翻倍。如果b表属于n的关系,这时我们不能去掉b表,因为这时关联之后数据量会翻番。
在本书后面的标量子查询等价改写、半连接等价改写以及SQL优化案例章节中我们就会用到表与表之间关系这个重要的概念。