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
出于三个原因:
适用于任何
SELECT
列表:单个表达式(您的 fiddle )、多个或整行(您在问题中的示例)。您可以区分实际的
NULL
来自“无行”的值。自user_id
是示例中的 PK(因此为NOT NULL
),问题无法在示例中显现。但表达式可以是NULL
,COALESCE
无法区分两者,“无行”被强制为NULL
出于查询的目的。请参阅:更快。
除此之外,你的第一个 SELECT
在这个例子中,这使得这成为一场徒劳的追逐。如果至少有一行,则返回一行。在这种情况下,其余的都是噪音。
相关:
关于sql - Postgres 执行合并中的所有子查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60907039/