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優化案例章節中我們就會用到表與表之間關系這個重要的概念。
推薦閱讀
- Cocos2D-X權威指南(第2版)
- Android Jetpack開發:原理解析與應用實戰
- 小創客玩轉圖形化編程
- Cocos2d-x游戲開發:手把手教你Lua語言的編程方法
- 云計算通俗講義(第3版)
- Python數據分析從0到1
- UVM實戰
- Corona SDK Mobile Game Development:Beginner's Guide(Second Edition)
- Natural Language Processing with Java and LingPipe Cookbook
- 新印象:解構UI界面設計
- Qlik Sense? Cookbook
- Web開發的平民英雄:PHP+MySQL
- Building Microservices with Go
- The Python Apprentice
- Mastering Linux Kernel Development