Sql 查询优化器是否能够从WHERE子句中提取有效常量以避免重复计算?
重写一个如下所示的函数是否会带来性能方面的好处:Sql 查询优化器是否能够从WHERE子句中提取有效常量以避免重复计算?,sql,postgresql,query-optimization,Sql,Postgresql,Query Optimization,重写一个如下所示的函数是否会带来性能方面的好处: CREATE FUNCTION some_text_predicate(name text) RETURNS boolean AS $$ SELECT EXISTS (SELECT 1 FROM sc.foo WHERE foo.name = some_transform(name) ); $$ LANGUAGE SQL; 因此: CREATE FUNCTION some_text_predicate(text)
CREATE FUNCTION some_text_predicate(name text) RETURNS boolean AS $$
SELECT EXISTS (SELECT 1 FROM sc.foo
WHERE foo.name = some_transform(name)
);
$$ LANGUAGE SQL;
因此:
CREATE FUNCTION some_text_predicate(text) RETURNS boolean AS $$
DECLARE
name text := some_transform($1);
BEGIN
RETURN EXISTS (SELECT 1 FROM sc.foo
WHERE foo.name = name
);
END;
$$ LANGUAGE plpgsql;
基本原理是,some_transform
的结果是一个常量,不需要在执行WHERE
子句的每一行上重新计算。查询优化器是否足够聪明,可以将其提取为常量,或者我必须使用第二个函数定义才能获得我想要的好处
我正在寻找优化
WHERE
子句求值的详细信息。这一切都取决于查询的某些转换
如果该函数是不可变的
(保证对相同的参数返回相同的结果)或稳定的
(在当前查询期间对相同的参数返回相同的结果,并且不修改数据库),则可以将函数标记为相同的
然后优化器将知道,如果参数在查询期间保持不变,则只需对函数求值一次
在计划查询时,将对不可变的
函数进行评估,在执行时对稳定的
函数进行评估
这将有助于您处理以下查询:
WHERE a.x = some_text_predicate('const')
但不是用
WHERE some_text_predicate(a.x) = 'const'
如果你能从中获益,我更喜欢第一个函数,因为它更简单
如果无法避免经常调用该函数,那么第二个函数可能更好,因为PL/pgSQL函数缓存执行计划。但是您无法避免这样多次调用昂贵的函数。如果您将某些转换
标记为稳定
或不可变
,以更合适的为准,它只会被计算一次。如果SQL函数被声明为稳定的
或不可变的
,那么它不也是比PL/pgSQL开销更有效的内联的候选者吗?如果它包含子查询,则不会。即使某些转换是不可变的,我无法将某些\u text\u谓词标记为不可变,因为它的结果取决于sc.foo的内容,对吗?对,它将是稳定的
。