官术网_书友最值得收藏!

關系型數據庫中,表與表之間會進行關聯,在進行關聯的時候,我們一定要理清楚表與表之間的關系。表與表之間存在3種關系。一種是1∶1關系,一種是1∶N關系,最后一種是NN關系。搞懂表與表之間關系,對于SQL優化、SQL等價改寫、表設計優化以及分表分庫都有巨大幫助。

兩表在進行關聯的時候,如果兩表屬于1∶1關系,關聯之后返回的結果也是屬于1的關系,數據不會重復。如果兩表屬于1∶N關系,關聯之后返回的結果集屬于N的關系。如果兩表屬于NN關系,關聯之后返回的結果集會產生局部范圍的笛卡兒積,NN關系一般不存在內/外連接中,只能存在于半連接或者反連接中。

如果我們不知道業務,不知道數據字典,怎么判斷兩表是什么關系呢?我們以下面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優化案例章節中我們就會用到表與表之間關系這個重要的概念。

主站蜘蛛池模板: 汤原县| 苏尼特右旗| 隆子县| 西宁市| 漠河县| 黄石市| 龙州县| 宁明县| 乐昌市| 滕州市| 岳池县| 时尚| 唐山市| 宁城县| 无极县| 清镇市| 中江县| 驻马店市| 逊克县| 苗栗县| 靖州| 麦盖提县| 昭平县| 老河口市| 宜宾县| 晋江市| 北京市| 屏山县| 定日县| 翁牛特旗| 墨脱县| 进贤县| 瑞丽市| 闽侯县| 定西市| 荣昌县| 诏安县| 博罗县| 武安市| 南丰县| 陵水|