【发布时间】:2016-12-02 00:45:22
【问题描述】:
我正在寻找创建一个 Postgres 函数来缓存长时间运行的查询的结果,因此它只需要在每个事务中执行一次:
CREATE OR REPLACE FUNCTION get_records (
_state VARCHAR(10)
)
RETURNS TABLE (
id UUID
) AS
$$
DECLARE
_temptable VARCHAR;
BEGIN
_temptable := FORMAT('temp_state_%s', _state);
IF NOT EXISTS(SELECT 1 FROM pg_tables WHERE tablename = _temptable) THEN
EXECUTE FORMAT('CREATE TEMPORARY TABLE %I (id UUID NOT NULL, PRIMARY KEY(_uid)) ON COMMIT DROP', _temptable);
EXECUTE FORMAT('INSERT INTO %I SELECT id FROM very_complex_nested_query', _temptable);
EXECUTE FORMAT('ANALYZE %I', _temptable);
END IF;
RETURN QUERY EXECUTE FORMAT('SELECT id FROM %I', _temptable);
END;
$$
LANGUAGE 'plpgsql';
现在,我可以运行所有查询并加入此函数:
SELECT mt.*
FROM my_table1 mt
INNER JOIN get_records('new') nr ON mt.id = nr.id
SELECT mt.*
FROM my_table2 mt
INNER JOIN get_records('new') nr ON mt.id = nr.id
SELECT mt.*
FROM my_table3 mt
INNER JOIN get_records('new') nr ON mt.id = nr.id
-- ... many more
我有一大堆这些,不保证哪个会先运行或按什么顺序运行。
这很好用,只是没有使用临时表上的主键索引。
如何从 Postgres 函数返回“表”,而不仅仅是查询的结果?
- 我正在使用函数来构建临时表而不是物化视图来解决“where clause doesn't get pushed into view that contains aggregation”问题。
- 我可以创建临时表,然后在所有查询中直接引用它,但这意味着必须构建某种阻塞机制以确保查询不会过早执行,而我正在使用的工具using 不能很好地支持这种机制。
【问题讨论】:
-
不要创建临时表,不要使用临时表。不要分析临时表。将“very_complex_nested_query”放入一个普通的
sql函数中。使用sql函数的查询可以比 PL/pgSQL 呈现给优化器的黑盒更好地优化。 -
@a_horse_with_no_name 但是......“very_complex_nested_query”需要 5 分钟才能执行,并且由于我将结果加入到数百个单独的查询中,因此我将在总执行时间中增加天数。这不是临时表的确切用例吗? “普通 sql 函数”是什么意思?
-
我的意思是
language sq而不是language plpgsql——但是如果你想索引它,你需要在临时表上创建一个索引。 -
@a_horse_with_no_name 你如何创建一个动态命名的临时表并在同一个查询中使用纯 sql 加入它?我不能保证查询的顺序,所以临时表可能会在任何查询中创建,我不想多次创建它。我正在寻求实现“缓存未命中:工作、缓存和返回”的设计。
-
SQL 函数将仅包含 SELECT 语句,不包含临时表。您仍然以相同的方式使用它,但 Postgres 能够优化整个查询包括一个inside函数。像这样:dpaste.com/1J5REFJ
标签: postgresql