连接类型和方法
连接是SQL语言的一个关键特性;它们是其力量和灵活性的基础。行集(要么直接从表中检索,要么作为某些其他操作的结果接收)总是成对连接。
有几种类型的连接:
-
内连接。 内连接(指定为“INNER JOIN”或简称为“JOIN”)由满足特定连接条件的两个集合的行对组成。连接条件将一组行的一些列与另一组行的一些列结合起来;所有涉及的列都构成连接键。
如果连接条件要求两个集合的连接键相等,这样的连接称为等连接(equi-join) ;这是最常见的连接类型。
两个集合的笛卡尔积(CROSS JOIN) 包含了这些集合的所有可能的行对——它是具有真条件的内连接的一种特殊情况。 -
外连接。 左外部连接(指定为“LEFT OUTER”或简称“LEFT JION”)通过左集中没有与右集中匹配的行(相应的右侧列填充为NULL值)扩展内部连接的结果。
对于右连接(RIGHT JOIN)也是如此,直到集合的排列。
完整的外部连接(指定为FULL JOIN)包括左外部连接和右外部连接,添加没有找到匹配的右侧和左侧行。 -
反连接(ANTI-JOIN)及半连接(SEMI-JOIN)。 半连接看起来很像内部连接,但它只包括左集中与右集中有匹配的行(即使有几个匹配,也只包括一行)。
反连接包括一个集合中在另一个集合中没有匹配的行。
SQL语言没有显式的半连接和反连接,但是使用像“EXISTS”和“NOT EXISTS”这样的谓词也可以达到同样的结果。
所有这些连接都是逻辑操作。例如,内部连接通常被描述为已经清除了不满足连接条件的行的笛卡尔积。但是在物理级别上,内连接通常是通过成本较低的方式实现的。
PostgreSQL提供几种连接方法:
- nested loop join
- hash join
- merge join
连接方法是实现SQL连接的逻辑操作的算法。这些基本算法通常具有为特定连接类型量身定制的特殊风格,即使它们可能只支持其中的一些。例如,嵌套循环支持内部连接(在计划中由嵌套循环节点表示)和左外部连接(由嵌套循环左连接节点表示),但它不能用于完全连接。
相同算法的某些风格也可以用于其他操作,例如聚合。
不同的连接方式在不同的条件下表现最佳;优化器的工作是选择最具成本效益的一种。
嵌套循环连接(Nested loop Joins)
嵌套循环连接函数的基本算法如下:外部循环遍历第一个集合(称为外部集合)的所有行。对于这些行中的每一行,将遍历第二组(称为内部集合)的行,以查找满足连接条件的行。 每个找到的对都会作为查询结果的一部分立即返回。
该算法访问内部集合的次数与外部集合的行数相同。因此,嵌套循环连接的效率取决于以下几个因素:
- 行外部集合的基数
- 可用的访问方法,可以有效地获取内部集所需的行
- 循环访问内部集合的同一行
笛卡尔积
不管集合中有多少行,嵌套循环连接是找到笛卡尔积的最有效方法:
嵌套循环节点使用上述算法执行连接。它总是有两个子节点:在计划中显示较高的一个对应于外部行集,而较低的一个代表内部行集。
在本例中,内部集合由Materialize节点表示。该节点返回从其子节点接收到的行,并保存它们以备将来使用(这些行在内存中累积,直到它们的总大小达到work_mem;然后PostgreSQL开始将它们溢出到磁盘上的临时文件中)。如果再次访问,该节点将读取累积的行,而不调用子节点。因此,执行器可以避免再次扫描整个表,而只读