由于Postgres具有LATERAL连接的能力,因此我一直在阅读,因为我目前为团队执行复杂的数据转储,其中包含许多效率低下的子查询,使得整个查询需要四分钟或更长时间。
我知道LATERAL联接可能会为我提供帮助,但是即使从Heap Analytics中阅读了类似这样的文章,我仍然不太了解。
联接的用例是LATERAL什么?LATERAL联接和子查询之间有什么区别?
什么是一个LATERAL加入? 该功能是PostgreSQL 9.3中引入的。 引用手册:
出现的子查询FROM之前可以带有关键字 LATERAL。这使他们可以引用前面的FROM项目提供的列 。(没有LATERAL,每个子查询都是独立评估的,因此不能交叉引用任何其他FROM项目。)
出现的表函数FROM也可以在关键字之后LATERAL,但是对于函数,关键字是可选的;例如:FROM在任何情况下,函数的参数都可以包含对前面各项提供的列的引用。
更像是相关子查询 甲LATERAL联接更像是一个相关子查询,而不是一个简单的子查询,在该表达式的右侧LATERAL连接中一次左的它的每一行评价-就像一个相关子查询-而平原子查询(表表达式)一次只要。(不过,查询计划器可以通过其中一种方法来优化性能。) 并排使用示例代码的相关答案,解决了相同的问题:
优化GROUP BY查询以检索每个用户的最新行 对于返回多个列,LATERAL联接通常更简单,更干净,更快。 另外,请记住,相关子查询的等效项是LEFT JOIN LATERAL … ON true:
多次调用带有数组参数的set-returning函数 子查询不能做的事情 有是事,一个LATERAL连接可以做,但一(相关的)子查询不能(容易)。相关的子查询只能返回一个值,不能返回多列,不能返回多行-裸函数调用(如果结果行返回多行,则结果行相乘)除外。但是,即使某些子集返回函数也只能在该FROM子句中使用。与unnest()Postgres 9.4或更高版本中的多个参数一样。手册:
这仅在FROM子句中允许;
因此这可行,但不能(轻松地)用子查询替换:
CREATE TABLE tbl (a1 int[], a2 int[]); SELECT * FROM tbl, unnest(a1, a2) u(elem1, elem2); -- implicit LATERAL
子句中的逗号(,)FROM是的缩写CROSS JOIN。LATERAL表功能自动假定。关于以下特殊情况UNNEST( array_expression [, … ] ):
如何声明仅在FROM子句中允许使用set-returning-function? SELECT列表中的集合返回功能 您还可以像unnest()在SELECT列表中一样直接使用返回集合的功能。在过去的SELECTPostgres 9.6列表中,它经常表现出令人惊讶的行为,并且具有多个这样的功能。但是它终于用Postgres 10进行了消毒,并且现在是有效的替代方法(即使不是标准的SQL)。看:
SELECT子句中的多个返回集合的函数的预期行为是什么? 在以上示例的基础上:
SELECT *, unnest(a1) AS elem1, unnest(a2) AS elem2 FROM tbl;
澄清错误信息 手册:
对于INNER和OUTER连接类型,必须指定一个连接条件,即NATURAL、、ON join_condition或USING(join_column [,...])中的一个。含义见下文。对于CROSS JOIN,这些子句都不会出现。
NATURAL、、ON join_condition或USING(join_column [,...])
因此,这两个查询是有效的(即使不是特别有用):
SELECT * FROM tbl t LEFT JOIN LATERAL (SELECT * FROM b WHERE b.t_id = t.t_id) t ON TRUE; SELECT * FROM tbl t, LATERAL (SELECT * FROM b WHERE b.t_id = t.t_id) t;