PostgreSQL函数中是否可以缓存变量



上下文

我正在构建一个Postgres扩展,它增加了使用语言变量询问模糊查询的可能性。例如:

SELECT age~=('age'|>'adult') FROM people;

将返回一个人是成年人这一事实的合理性(成年人被定义为梯形函数30/40~6065.

问题

我做了一个函数,允许返回指定值和语言变量的语言名称:

SELECT age, age~>'age' FROM people;

返回

age | age~>'age'
-----+--------------
20  | young adult
10  | child
45  | adult
60  | old

此函数和运算符的来源如下:

CREATE FUNCTION get_fuzzy_name(
input FLOAT8,
type_name VARCHAR(64)
) RETURNS VARCHAR(64) AS $$
DECLARE
type_id fuzzy.types.id%TYPE;
deg FLOAT8;
result_name VARCHAR(64);
BEGIN
type_id := get_fuzzy_type(type_name); -- returns type's id based on it's name
SELECT
degree(input, fun) AS d, name
INTO
deg, result_name
FROM fuzzy.functions
WHERE type=type_id
ORDER BY d DESC LIMIT 1;
IF deg=0 THEN
RETURN NULL;
END IF;
RETURN result_name;
END;
$$ LANGUAGE plpgsql IMMUTABLE STRICT;
CREATE OPERATOR ~> (
PROCEDURE = get_fuzzy_name,
LEFTARG = FLOAT8,
RIGHTARG = VARCHAR(64)
);

问题是,对于每一行,上面的函数都会一次又一次地查询模糊类型和函数。所以我提出了这个,作为改进的基础(模糊函数保存在一个变量中(:

CREATE TYPE FUZZY_TYPE_FUNCTION AS (
func  TRAPEZOIDAL_FUNCTION,
range_name VARCHAR(64)
);
CREATE FUNCTION get_fuzzy_name(
input FLOAT8,
type_name VARCHAR(64)
) RETURNS VARCHAR(64) AS $$
DECLARE
f FUZZY_TYPE_FUNCTION;
_type_functions FUZZY_TYPE_FUNCTION[] := array(SELECT (fun, name) FROM fuzzy.functions WHERE fuzzy.functions.type=type_name);
_deg_tmp FLOAT8;
_deg FLOAT8;
_result_name VARCHAR(64);
BEGIN
_deg := 0;
FOREACH f IN array(_type_functions) LOOP
_deg_tmp := degree(input, f.func);
RAISE NOTICE '% && % = %', f, input, _deg_tmp;
IF _deg<_deg_tmp THEN
_deg := _deg_tmp;
_result_name := f.range_name;
EXIT WHEN _deg=1;
END IF;
END LOOP;
IF _deg=0 THEN
RETURN NULL;
END IF;
RETURN _result_name;
END;
$$ LANGUAGE plpgsql IMMUTABLE STRICT;

有没有一种方法可以在每个查询中只获取一次函数表的值并缓存它,这样它就可以重用并大大加快整个查询的速度?

附加信息

根据要求,以下是表格:

CREATE SCHEMA IF NOT EXISTS fuzzy;
CREATE TABLE IF NOT EXISTS fuzzy.types (
id   SERIAL PRIMARY KEY,
name VARCHAR(64) UNIQUE
);
CREATE TABLE IF NOT EXISTS fuzzy.functions (
type INT                  NOT NULL,
fun  TRAPEZOIDAL_FUNCTION NOT NULL,
name VARCHAR(64),
FOREIGN KEY (type) REFERENCES fuzzy.types (id) ON DELETE CASCADE,
UNIQUE (type, name)
);

CCD_ 2可能包含作为id-name对的几行,fuzzy.functions很可能每种类型包含3-10行,对于大量使用的情况,这可能是大约500行(我想(。

您可能正在构建关于函数性能的几个误导性假设。

请尝试这个简化的SQL函数:

CREATE FUNCTION get_fuzzy_name(_input FLOAT8, _type_name VARCHAR(64))
RETURNS VARCHAR(64) AS
$func$
SELECT f.name
FROM   fuzzy.functions f
JOIN   fuzzy.types     t ON t.id = f.type
WHERE  t.name = _type_name
AND    degree(_input, f.fun) > 0
ORDER  BY degree(_input, f.fun) DESC
LIMIT  1;
$func$  LANGUAGE sql STABLE;
  • LANGUAGE sql。没有变量、赋值、IF构造。。。1个简单查询。完全重写,但应该是等效的。

  • STABLE而不是IMMUTABLE

  • 根本没有嵌套函数调用。已替换为联接。应该更便宜。

  • 然而,内联未公开的degree()函数可能更便宜May甚至可以简化为更快的"最近邻居"查询。信息不足。

  • 与原来的函数不同,这个函数可以内联。我删除了STRICT,这可能会妨碍我。无法告知,信息不足。

请参阅Postgres Wiki中有关标量函数内联的内容
和:

  • 函数在没有STRICT修饰符的情况下执行得更快

相关:

  • PostgreSQL UDF(用户定义函数(开销

最新更新