sql - Postgres 执行合并中的所有子查询

标签 sql database postgresql

Postgres 中的 COALESCE 是一个返回第一个参数不为空的函数。 所以我在子查询中使用了合并,例如:

SELECT COALESCE (
 ( SELECT * FROM users WHERE... ORDER BY ...),
 ( SELECT * FROM users WHERE... ORDER BY ...),
 ( SELECT * FROM users WHERE... ORDER BY ...),
 ( SELECT * FROM users WHERE... ORDER BY ...)
);

我更改了任何查询中的 where ,它们包含大量参数和 CASE,还有不同的 ORDER BY 子句。 这是因为我总是想返回一些东西,但要优先考虑。

我在发出EXPLAIN ANALYZE时注意到的是,尽管第一个查询实际上返回非空值,但任何查询都会被执行。 我希望引擎只运行第一个查询,如果返回不为空,则不运行后续查询。

这样我的表现可能会很差。

那么我是否做了任何不好的做法,出于性能原因单独运行查询是否更好?

编辑:

抱歉,我没有选择*,但我只选择了一列。我没有发布我的代码,因为我对我的查询不感兴趣,但这是了解引擎如何工作的通用问题。所以我在这里重现一个非常简单的 fiddle http://sqlfiddle.com/#!17/a8aa7/4

我可能是错的,但我认为它的行为正如我所说:它运行所有子查询,尽管第一个子查询已经返回一个非空值

编辑2:好的,我现在只读了,它说从未执行过。所以其他两个查询没有被执行。让我困惑的是它们包含在查询计划中。

无论如何,这对我的问题仍然很重要。出于性能原因,单独运行所有查询是否更好?因为看起来即使第一个子查询返回非空值,其他两个子查询也会降低性能

最佳答案

对于单独的SELECT查询,我建议使用 UNION ALL/LIMIT 1反而。基于your fiddle :

(select user_id from users order by age limit 1)  -- misleading example, see below
UNION ALL
(select user_id from users where user_id=1)
UNION ALL
(select user_id from users order by user_id DESC limit 1)
LIMIT 1;

db<> fiddle here

出于三个原因:

  1. 适用于任何 SELECT列表:单个表达式(您的 fiddle )、多个或整行(您在问题中的示例)。

  2. 您可以区分实际的NULL来自“无行”的值。自 user_id是示例中的 PK(因此为 NOT NULL ),问题无法在示例中显现。但表达式可以是 NULL , COALESCE无法区分两者,“无行”被强制为 NULL出于查询的目的。请参阅:

  3. 更快。

除此之外,你的第一个 SELECT在这个例子中,这使得这成为一场徒劳的追逐。如果至少有一行,则返回一行。在这种情况下,其余的都是噪音。

相关:

关于sql - Postgres 执行合并中的所有子查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60907039/

相关文章:

sql - 分区表查询仍在扫描所有分区

javascript - 使用 Javascript 和 PLV8 在 Postgresql 中计算重复事件

sql - redshift select distinct 返回重复值

sql - 从 3 个数据库表中获取数据

php - 如何在 INSERT 查询中使用 JOIN?

sql - 在交易中设置时间戳

sql - 一系列正负百分比的总百分比

hibernate - org.hibernate.NonUniqueObjectException

sql - 对于多对多关系,从多中搜索一个

mysql - MySQL 8.0 中使用的 CONTAINS 关键字是什么?