Atitit 数据存储的数据表连接attilax总结

1.1. 三种物理连接运算符:嵌套循环连接、合并连接以及哈希连接1

1.2. a、嵌套循环连接(nested loops join)1

1.3. b、合并连接(merge join)3

1.4. c、哈希连接(hash join) 4

1.5. 所以这三种算法,没有谁好谁坏,只有合适的场景应用合适的连接算法,这样才能发挥它自身的长处,而恰巧这些就是我们要掌握的技能。6

1.6. 这三种连接算法我们也可以显示的指定,loop merger hash6

1.7. 所有的最优计划的选择都是基于现有统计信息来评估,7

1.8. 参考资料7

1.1. 三种物理连接运算符:嵌套循环连接、合并连接以及哈希连接

默认支持三种物理连接运算符:嵌套循环连接、合并连接以及哈希连接。三种连接各有用途,各有特点,不同的场景会数据库会为我们选择最优的连接方式。

1.2. a、嵌套循环连接(nested loops join)

嵌套循环连接是最简单也是最基础的连接方式。两张表通过关键字进行关联,然后通过双层循环依次进行两张表的行进行关联,然后通过关键字进行筛选。

可以参照下图进行理解分析

其实嵌套扫描是很简单的获取数据的方式,简单点就是两层循环过滤出结果值

我们可以通过如下代码加深理解

for each row R1 in the outer table

for each row R2 int the inner table

if R1 join with R2

return (R1,R2)

举个列子

SELECT o.OrderID

FROM Customers C JOIN Orders O

ON C.CustomerID=O.CustomerID

WHERE C.City=N'London'

这种方法的消耗就是外表和内表的乘积,其实就是我们所称呼的笛卡尔积。所以消耗的大小是随着两张表的数据量增大而增加的,尤其是内部表,因为它是多次重复扫描的,所以我们在实践中的采取的措施就是减少每个外表或者内表的行数来减少消耗。

对于这种算法还有一种提高性能的方式,因为两张表是通过关键字进行关联的,所以在查询的时候对于底层的数据获取速度直接关乎着此算法的性能,这里优化的方式尽量使用两个表关键字为索引查询,提高查询速度。

还有一点就是在嵌套循环连接中,在两张表关联的时候,对外表都是有筛选条件的,比如上面例子中【WHERE C.City=N'London'】就是对外表(Customers)的筛选,并且这里的City列在该表中存在索引,所以该语句的两个子查询都为索引查找(Index Seek)。

但是,有些情况我们的查询条件不是索引所覆盖的,这时候,在嵌套循环连接下的子运算符就变成了索引扫描(Index scan)或者RID查找。

举个例子

通过文本可以看出,该T-SQL的查询结果的获取是通过在嵌套循环运算符中,对两个表经过全表扫描之后形成的笛卡儿积进行过滤筛选的。这种方式其实不是一个最优的方式,因为我们获取的结果其实是可以先通过两个表过滤之后,再通过嵌套循环运算符获取结果,这样的话性能会好很多。

我们尝试改一下这个语句

SELECT E1.EmployeeID,ECNT.CNT

FROM Employees E1 CROSS APPLY

(

SELECT COUNT(*) CNT

FROM Employees E2

WHERE E1.HireDate<E2.HireDate

)ECNT

通过上述代码查询的结果项,和上面的是一样的,只是我们根据外部表的结果对内部表进行了过滤,这样执行的时候就不需要获取全部数据项了

所以对嵌套循环连接连接的优化方式就是集中在这几点:对两张表数据量的减少、连接关键字上建立索引、谓词查询条件上覆盖索引最好能减少符合谓词条件的记录数。

1.3. b、合并连接(merge join)

上面提到的嵌套循环连接方式存在着诸多的问题,尤其不适合两张表都是大表的情况下,因为它会产生N多次的全表扫描,很显然这种方式会严重的消耗资源。

鉴于上述原因,在数据库里又提供了另外一种连接方式:合并连接。记住这里没有说SQL Server所提供的,是因为此连接算法是市面所有的RDBMS所共同使用的一种连接算法。

合并连接是依次读取两张表的一行进行对比。如果两个行是相同的,则输出一个连接后的行并继续下一行的读取。如果行是不相同的,则舍弃两个输入中较少的那个并继续读取,一直到两个表中某一个表的行扫描结束,则执行完毕,所以该算法执行只会产生每张表一次扫描,并且不需要整张表扫描完就可以停止。

该算法要求按照两张表进行依次扫描对比,但是有两个前提条件:1、必须预先将两张表的对应列进行排序;2、对两张表进行合并连接的条件必须存在等值连接。

1.4. c、哈希连接(hash join) 

我们分析了上面的两种连接算法,两种算法各有特点,也各有自己的应用场景:嵌套循环连接适合于相对小的数据集连接,合并连接则应对与中型的数据集,但是又有它自己的缺点,比如要求必须有等值连接,并且需要预先排序等。

那对于大型的数据集合的连接数据库是怎么应对的呢?那就是哈希连接算法的应用场景了。

哈希连接对于大型数据集合的并行操作上都比其它方式要好很多,尤其适用于OLAP数据仓库的应用场景中。

哈希连接很多地方和合并连接类似,比如都需要至少一个等值连接,同样支持所有的外连接操作。但不同于合并连接的是,哈希连接不需要预先对输入数据集合排序,我们知道对于大表的排序操作是一个很大的消耗,所以去除排序操作,哈希操作性能无疑会提升很多。

哈希连接在执行的时候分为两个阶段:

· 构建阶段

在构建阶段,哈希连接从一个表中读入所有的行,将等值连接键的行机型哈希话处理,然后创建形成一个内存哈希表,而将原来列中行数据依次放入不同的哈希桶中。

· 探索阶段

在第一个阶段完成之后,开始进入第二个阶段探索阶段,该阶段哈希连接从第二个数据表中读入所有的行,同样也是在相同的等值连接键上进行哈希。哈希过程桶上一阶段,然后再从哈希表中探索匹配的行。

上述的过程中,在第一个阶段的构建阶段是阻塞的,也就是说在,哈希连接必须读入和处理所有的构建输入,之后才能返回行。而且这一过程是需要一块内存存储提供支持,并且利用的是哈希函数,所以相应的也会消耗CPU等。

并且上述流程过程中一般采用的是并发处理,充分利用资源,当然系统会对哈希的数量有所限制,如果数据量超大,也会发生内存溢出等问题,而对于这些问题的解决,SQL Server有它自身的处理方式。

我们可通过以下代码进行理解

我们来总结一下这个算法的特点

· 和合并连接一样算法复杂度基本就是分别遍历两边的数据集各一遍

· 它不需要对数据集事先排序,也不要求上面有什么索引,通过的是哈希算法进行处理

· 基本采取并行的执行计划的方式

但是,该算法也有它自身的缺点,因为其利用的是哈希函数,所以运行时对CPU消耗高,同样对内存也比较大,但是它可以采用并行处理的方式,所以该算法用于超大数据表的连接查询上显示出自己独有的优势。

关于哈希算法在哈希处理过程的时候对内存的占用和分配方式,是有它自己独有哈希方法,比如:左深度树、右深度树、浓密哈希连接树等,这里不做详细介绍了,只需要知道其使用方式就可以了。

Hash Join并不是一种最优的连接算法,只是它对输入不优化,因为输入数据集特别大,并且对连接符上有没有索引也没要求。其实这也是一种不得已的选择,但是该算法又有它适应的场景,尤其在OLAP的数据仓库中,在一个系统资源相对充足的环境下,该算法就得到了它发挥的场景。

当然前面所介绍的两种算法也并不是一无是处,在业务的OLTP系统库中,这两种轻量级的连接算法,以其自身的优越性也获得了认可。

1.5. 所以这三种算法,没有谁好谁坏,只有合适的场景应用合适的连接算法,这样才能发挥它自身的长处,而恰巧这些就是我们要掌握的技能。

1.6. 这三种连接算法我们也可以显示的指定,loop merger hash

但是一般不建议这么做,因为默认SQL Server会为我们评估最优的连接方式进行操作,当然有时候它评估不对的时候就需要我们自己指定了,方法如下:

1.7. 所有的最优计划的选择都是基于现有统计信息来评估,

 而上面关于这两列内容分布类型SQL Server是怎样知道的?这就是SQL Server的强大的统计信息在支撑了。

在SQL Server中并不是固定的语句就会形成特定的计划,并且生成的特定计划也不是总是最优的,这和数据库现有数据表中的内容分布、数据量、数据类型等诸多因素有关,而记录这些详细信息的就是统计信息。

所有的最优计划的选择都是基于现有统计信息来评估,如果我们的统计信息未及时更新,那么所评估出来最优的执行计划将不是最好的,有时候反而是最烂的。

1.8. 参考资料

SQL Server调优系列基础篇(常用运算符总结——三种物理连接方式剖析) - 指尖流淌 - 博客园.html

作者:: 绰号:老哇的爪子claw of Eagle 偶像破坏者Iconoclast image-smasher

捕鸟王"Bird Catcher 王中之王King of Kings 虔诚者Pious 宗教信仰捍卫者 Defender of the Faith. 卡拉卡拉红斗篷 Caracalla red cloak

简称:: Emir Attilax Akbar 埃米尔 阿提拉克斯 阿克巴

全名::Emir Attilax Akbar bin Mahmud bin  attila bin Solomon Al Rapanui

埃米尔 阿提拉克斯 阿克巴 本 马哈茂德 本 阿提拉 本 所罗门  阿尔 拉帕努伊

常用名:艾提拉(艾龙),   EMAIL:1466519819@qq.com

转载请注明来源:attilax的专栏   http://www.cnblogs.com/attilax/

--Atiend

Atitit 数据存储的数据表连接attilax总结的更多相关文章

  1. Atitit 研发体系建立 数据存储与数据知识点体系知识图谱attilax 总结

    Atitit 研发体系建立 数据存储与数据知识点体系知识图谱attilax 总结 分类具体知识点原理规范具体实现(oracle,mysql,mssql是否可以自己实现说明 数据库理论数据库的类型 数据 ...

  2. Atitit.数据库存储引擎的原理与attilax 总结

    Atitit.数据库存储引擎的原理与attilax 总结 1. 存储引擎是什么1 2. 其它数据库系统(包括大多数商业选择)仅支持一种类型的数据存储2 3. 表的存储有三个文件:结构+数据+索引2 4 ...

  3. Atitit.数据库存储引擎的原理与attilax 总结

    Atitit.数据库存储引擎的原理与attilax 总结 1. 存储引擎是什么1 2. 其它数据库系统(包括大多数商业选择)仅支持一种类型的数据存储2 3. 表的存储有三个文件:结构+数据+索引2 4 ...

  4. Spring Boot 揭秘与实战(二) 数据存储篇 - 数据访问与多数据源配置

    文章目录 1. 环境依赖 2. 数据源 3. 单元测试 4. 源代码 在某些场景下,我们可能会在一个应用中需要依赖和访问多个数据源,例如针对于 MySQL 的分库场景.因此,我们需要配置多个数据源. ...

  5. 【Hive】Hive笔记:Hive调优总结——数据倾斜,join表连接优化

    数据倾斜即为数据在节点上分布不均,是常见的优化过程中常见的需要解决的问题.常见的Hive调优的方法:列剪裁.Map Join操作. Group By操作.合并小文件. 一.表现 1.任务进度长度为99 ...

  6. python3下scrapy爬虫(第十二卷:解决scrapy数据存储大量数据时阻塞问题)

    之前我们使用scrapy爬取数据,用的存储方式是直接引入PYMYSQL,或者MYSQLDB,案例中数据量并不大,这种数据存储方式属于同步过程,也就是上一条语句执行完才能执行下一条语句,当数据量变大时, ...

  7. IOS第13天(3,私人通讯录,登陆状态数据存储,数据缓存, cell的滑动删除,进入编辑模式,单个位置刷新 )

    *****联系人的界面的优化 HMContactsTableViewController.m #import "HMContactsTableViewController.h" # ...

  8. oracle表连接——处理连接过程中另外一张表没有相关数据不显示问题

    一个数据表基本上很难满足我们的查询要求,同时,将所有的数据都保存在一个表格中显然也不是一种好的数据库设计,为了避免数据的冗余,删除.更新异常,我们通常需要建立一张外键表,通过表连接,来获取我们自己想要 ...

  9. Mysql+innodb数据存储逻辑

    Mysql+innodb数据存储逻辑. 表空间由段,区,页组成 ibdata1:共享表空间.即所有的数据都存放在这个表空间内.如果用户启用了innodb_file_per_table,则每张表内的数据 ...

随机推荐

  1. 《UML大战需求分析》阅读笔记5

    流程分析利器三,顺序图. 顺序图描述的是一件事发生的顺序,按照时间的发展,事情的走向,其中分为角色,消息等,每个角色下面都有一条生命线,从上到下,从左到右,依次进行事件,没有事情的时候用虚线表示,而有 ...

  2. beanstalkd----安装启动

    1. 安装This is beanstalkd, a fast, general-purpose work queue.See http://kr.github.io/beanstalkd/ for ...

  3. php安装libiconv-1.14.tar.gz遇到的问题

    遇到的Error code In file included from progname.c:26:0: ./stdio.h:1010:1: error: ‘gets‘ undeclared here ...

  4. MATLAB 秒表函数 tic toc 计算程序运行时间

    若需要测试出程序运行所需时间,或对不同的运行方式所需时间进行对比,则可利用秒表函数tic和toc.Tic函数启动定时器,第一个紧跟它的toc函数终止定时器并报告此时定时器的流逝时间.其语法如下:  t ...

  5. 46. Permutations 回溯算法

    https://leetcode.com/problems/permutations/ 求数列的所有排列组合.思路很清晰,将后面每一个元素依次同第一个元素交换,然后递归求接下来的(n-1)个元素的全排 ...

  6. 我的Sharepoint视图的使用

    视图是个很灵活的工具,不过在使用前,为了更好的管理视图,我会将Contribute的权限的视图功能去掉. 普通用户都设为Contribute权限,有增删改操作就行. 这样做主要有三个目的: 1.不能让 ...

  7. Java-ios推送

    之前做的消息推送,向Android和ios客户端推送.这里只说ios的推送,ios的推送最后都会推送到苹果的APNS服务器上,再有APNS服务器推送到ios设备上.因为考虑到这一点,第一版的消息推送苹 ...

  8. 【C++】自绘控件基础

    由于我们对控件的功能.外观的需求,公共控件并不能很好地满足这一点,所以我们就得自绘控件. 自绘控件有许多方法,比如:处理WM_PAINT消息,设置ownDraw风格,处理WM_CTLCOLOR消息,等 ...

  9. Linux下搭建PHP环境

    转载于: http://www.uxtribe.com/php/405.html 该站下有系列PHP文章. 在Linux下搭建PHP环境比Windows下要复杂得多.除了安装Apache,PHP等软件 ...

  10. 工作当中实际运用(3)——js原生实现鼠标点击弹出div层 在点击隐藏

    function onmou(){ var divs=document.getElementById('kefuDV');//获取到你要操作的div if (divs.style.display==& ...