阅读本文可以了解PostgreSQL数据库中表与表不同的连接方式,如嵌套循环连接、合并连接和哈希连接;同时可以了解到不同连接方式的适用场景。
表连接是数据库查询中一种常见的操作,用于组合两个或多个表满足条件的数据。PostgreSQL数据库中的查询优化器(planner/optimizer)负责为给定的SQL查询创建最佳的执行计划。优化器回考虑多种可能的执行计划,并根据成本选择运行最快的一个。
优化器在生成可能的计划时,会考虑表连接的不同策略,包括嵌套循环连接、合并连接和哈希连接。
Nested Loop 是扫描一个外表,每读到一条记录,就根据 join 字段上的索引去另一张内表里面查找;
外表称为“驱动表”,一般为小表,不仅相对于其他表是小表,而且记录数的绝对值也较小,不要求有索引;外表返回的每一行都要在内表中检索找到与它匹配的行,因此整个查询返回的结果集不能太大(建议小于1万);
若内表 join 字段上没有索引,查询优化器一般不会选择 Nested Loop。
1. 无索引顺序扫描情况下图示:

1. 首先检索驱动表外侧表(全表扫描),获取到符合外侧表单独条件的记录行集合(row1和row2);2. 针对row1和row2,分别对inner表进行全表扫描匹配,就是对每个outer的结果行,要进行inner表的所有块查询,最终发现符合条件的row3和row4,将结果返回。我们可以发现Nest Loop Join存在大量的随机读。一个外表行,就需要进行内表的全表扫描;如果内表很大,那么执行计划效率就会很差。
2. 有索引情况下图示:

1. 有索引情况下,rows1和rows2可以直接确定符合条件的内部表数据行对应的位置,不需要直接对内表进行检索;2. 索引大小远小于内表,所以进行的块读取要少很多。
Merge join 在连接之前,每个关系都按照连接属性排序,然后并行扫描两个关系,匹配的行被整合成连接行。这种连接策略适用于两个表都很大并且连接键上有索引支持排序的情况。
merge join 可适用于非等值join (>、<、>=、<=、但是不包含!=、<>);
在全表扫描比索引范围扫描性能更加的情况下,Merge join会比Nested Loop性能更好;
通常情况下 Hash join 的效果都比排序合并连接要好,但是两表已经被排过序,在执行排序合并连接时不再需要排序了,则Merge join性能会更好。
Merge join 的过程如下图示:

1. Merge join首先从两个输入集合中各选取第一行,如果匹配,则返回匹配行;2. 假如有行不匹配,则有较小值的输入集合 +1,继续往匹配。
Hash join 过程分为两个主要阶段:
1. 构建阶段:首先选择一个表(通常选择较小的表作为内表),并根据连接条件的列值计算哈希值,将每个元组存储到内存中的哈希表的对应bucket中。这个哈希表通常也被称为内表。
2. 探测阶段:接下来扫描另一个表(外表),根据连接条件计算每个元组的哈希值,并使用这个值在已构建的hash表中寻找匹配的元组。如果找到匹配的元组并且满足所有查询条件,则输出到结果集合中。
使用于较小的表完全可以放入内存中的情况,这样总成本就是访问两张表成本之和;
如果表很大,不能完全放入内存,优化器会把他们分割成不同的分区,把不能放入到内存的部分写入磁盘的临时段,此时需要有较大的临时段以便提高I/O性能;
哈希连接是归并连接的主要替代方案,哈希连接并不会对输入进行排序;
能够很好的工作于没有索引的大表和并行查询环境中,并提供较好的性能。
Hash join 的过程如下图示:

1. 构建阶段:输入源中的每一个条目经过散列函数的计算都放到不同的hash bucket,注意条目是无序的;2. 探测阶段:对于另一个输入集合,同样针对每一行进行散列函数,确定其所在的hash bucket,再针对这行和对应hash bucket中的每一行进行匹配。3. 如果匹配成功则返回对应的行。
| Type | Nested Loop Join | Merge Join | Hash Join |
| 相关条件 | 任何条件 | 等值或非等值 | 等值连接 |
| 相关资源 | CPU、磁盘I/O | 内存、临时空间 | 内存、临时空间 |
| 特点 | 当高选择性索引或进行限制性搜索时效率较高,能够快速返回第一次搜索结果 | 当缺乏索引或索引条件模糊时,Merge Join比Nested Loop有效。非等值连接时,Merge Join比Hash Join有效 | 当缺乏索引索引条件模糊时,Hash Join比Nested Loop Join有效,通常比Merge Join块。 |
| 缺点 | 索引丢失或者查询条件不够时,效率很低;当表记录数很多的时候,效率低 | 所有表都需要排序,需要等待结果全部找到才返回数据 | 为建立hash表,需要大量内存,第一次返回结果较慢 |
本文内容就到这啦,阅读完本篇,相信你对PostgreSQL的连接方式相关知识有了更深的理解了吧!我们下篇再见!





