前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >可以拿来吊打面试官的 SQL Join (三)

可以拿来吊打面试官的 SQL Join (三)

作者头像
Lenis
发布2020-06-19 14:36:54
4040
发布2020-06-19 14:36:54
举报
文章被收录于专栏:有关SQL有关SQL

这是本系列第三篇。

点击下面链接,可以阅读上两篇:

可以拿来吊打面试官的 SQL Join (一) 可以拿来吊打面试官的 SQL Join (二)

我在这个系列中,所分享的知识,力求逻辑严谨,实战辅证。但一如所有的文章一样,读者需要自己思考,是否正确无误,是否可以拿来直接作用于生产环境。对于没有理解透彻,就直接用于生产而造成的损失,本人概不负责。

不仅仅是看我的文章,看所有的文章,书籍或者教程,读者朋友们都该用自己的思维,带着批判的眼光,谨慎对待作者发表的观点,切勿盲目轻信。

回到正题,上一讲中,文末留了个预告,这回要讲 WHERE 和 ON 时,对索引的访问方式,以及无索引时,访问效率如何提高。

拿上讲中的例子,来做探讨。基于公平的基础上,我们比较 WHERE 和 ON 的性能,实际可以归纳成比较下两个例子的快慢:

代码语言:javascript
复制
SELECT Header.OrderId
    ,   Detail.ProductName
    ,   Detail.Amount 
FROM tblOrderHeader Header 
    INNER JOIN tblOrderDetail Detail 
        ON Header.OrderId = Detail.OrderId 
        AND Detail.Amount > 1000
WHERE Header.OrderDate > '2020-01-01' 

Detail.Amount > 1000 放在 WHERE 中:

代码语言:javascript
复制
SELECT Header.OrderId
    ,   Detail.ProductName
    ,   Detail.Amount 
FROM tblOrderHeader Header 
    INNER JOIN tblOrderDetail Detail 
        ON Header.OrderId = Detail.OrderId 
WHERE Header.OrderDate > '2020-01-01' 
    AND Detail.Amount > 1000

从原业务库,复制了一份轻量型的数据。暂时还没加上索引,肯定是不够优化的。正是由于这份原始的数据,我们得以窥探,在没有任何索引的时候,两表怎么优化。

面对调优,我的黄氏三板斧,大家应该都不陌生了。如果是新关注的读者,可以到文末的搜索框里搜索。点击#三板斧#的标签即可。

在这里,用到执行计划。

以上就是二段 SQL 的执行计划。一模一样。

不出意外的,如果没有索引,那么表扫描(Table Scan)是唯一的 Join 解法。平时跟大家说,要懂点英语,要懂点英语,好处就在这里。Table Scan, Hash Match, 下次你面试的时候,听到这些词,就不会胆怯

按照 Table Scan 的图标,点进去,我们会有惊喜。

上面两个执行算子,都使用了 Predicate. Predicate 在这里的作用是条件判断。即筛选满足条件的记录。

Predicate 在 Table Scan 里面出现,说明它仅仅能减少结果数据集,不等于减少从磁盘读到的数据。因为 Table Scan 就说明了,数据的查找方式,是按照全表扫描方式进行的。

有细心的读者,可能会发现,这里有个 Hash Match (Inner Join).

好多读者对 Left Join, Right Join , Full Join 滚瓜烂熟。但对于 Hash Join, Merge Join, Nested Loop Join 是一点概念都没有

这大概就是不好好读书,带来的差别。

回忆下我们这两张表数据的来历,就知道,在Join字段上,并没有加索引。没有索引的情况下,Join 怎么提高性能呢?答案就是 Hash join. 至于它的原理,还有 Merge Join, Nested Loop Join 的内幕,我打算留到后面,找合适的机会再讲。其实,我的知识星球里面,早已写得很明白。

如何给这段 SQL 提高性能? 解决之道在于索引。

代码语言:javascript
复制
## 尝试给两表加索引

CREATE INDEX IDX_HEADER ON tblOrderHeader(OrderId)
CREATE INDEX IDX_DETAIL ON tblOrderDetail(OrderId)

## end 

但是呢,加了索引之后,发现执行时间还长了。真别不信,有时候 Table Scan 真要快很多。这就是个例子。

所以,我们继续要加索引:

代码语言:javascript
复制
CREATE INDEX IDX_HEADER_ORDER_DATE ON tblOrderHeader(OrderDate)
CREATE INDEX IDX_DETAIL_AMOUNT ON tblOrderDetail(Amount)

索引加对,速度爆表

等到加完索引,再回头比较两个 INNER JOIN, 其实他们的执行计划和速度都是一模一样的。

在本文中,提供了比较两个 Join 写法的思路,还有通过增加索引,提高性能的实战操作经验。现实环境中,条件比上面两个表,要复杂的多。可能需要花费我们一些耐心,才能找到最优解。

上面很多执行计划,其实都只写了一半,大家有可能看得云里雾里。没关系,下一文,我会继续展开讲解下在本章中出现的执行计划操作符。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-06-17,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 有关SQL 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档