PostgreSQL是否会短路其BOOL_OR()评估?

Luk*_*der 5 sql postgresql boolean-logic exists boolean-expression

EXISTSCOUNT(*)它可以短路更快

很多时候,我喜欢检查SQL中存在的东西.例如,我这样做:

-- PostgreSQL syntax, SQL standard syntax:
SELECT EXISTS (SELECT .. FROM some_table WHERE some_boolean_expression)

-- Oracle syntax
SELECT CASE 
  WHEN EXISTS (SELECT .. FROM some_table WHERE some_boolean_expression) THEN 1 
  ELSE 0 
END
FROM dual
Run Code Online (Sandbox Code Playgroud)

在大多数数据库中,EXISTS"短路",即一旦找到一行,数据库就可以停止在表中查找行.这通常比比较快得多,COUNT(*) >= 1正如本博文中所见.

使用EXISTSGROUP BY

有时,我想在GROUP BY查询中为每个组执行此操作,即我想"聚合"存在值.没有EXISTS聚合函数,但PostgreSQL幸运地支持BOOL_OR()聚合函数,就像在这个语句中一样:

SELECT something, bool_or (some_boolean_expression)
FROM some_table
GROUP BY something
Run Code Online (Sandbox Code Playgroud)

COUNT(*)由于计算计数所需的明显顺序扫描,文档提到了一些缓慢的问题.但不幸的是,它并没有说明BOOL_OR()被短路的事情.是这样的吗?BOOL_OR()一旦遇到第一个TRUE值,是否会停止聚合新值?

Mar*_*and 3

如果你想检查是否存在,我通常使用LIMIT/FETCH FIRST 1 ROW ONLY查询:

SELECT .. FROM some_table WHERE some_boolean_expression
FETCH FIRST 1 ROW ONLY
Run Code Online (Sandbox Code Playgroud)

这通常会在第一次命中后停止执行。

LATERAL可以对另一个表中的每一行(组)应用相同的技术。

SELECT * 
  FROM (SELECT something
          FROM some_table
         GROUP BY something
       ) t1
  LEFT JOIN LATERAL (SELECT ...
                        FROM ...
                       WHERE ...
                       FETCH FIRST 1 ROW ONLY) t2
    ON (true)
Run Code Online (Sandbox Code Playgroud)

t2可以使用WHERE与该组的任何行匹配的子句。每组只执行一次,并在发现第一个命中后立即中止。然而,当然,这表现得更好还是更差取决于您的搜索谓词和索引。