是否可以在 postgresql 中手动更改执行计划的操作顺序?例如,如果我总是希望在过滤之前进行排序操作(尽管它在 postgresql 的正常使用中没有意义),是否可以通过例如更改操作的内部成本来手动强制执行?
如果我实现自己的功能呢?是否有可能在 sql 语句的最后始终执行这样的函数?
是否可以在 postgresql 中手动更改执行计划的操作顺序?例如,如果我总是希望在过滤之前进行排序操作(尽管它在 postgresql 的正常使用中没有意义),是否可以通过例如更改操作的内部成本来手动强制执行?
如果我实现自己的功能呢?是否有可能在 sql 语句的最后始终执行这样的函数?
首先使用子查询或CTE强制执行某些操作。像:
SELECT *
FROM (
SELECT *
FROM tbl
LIMIT 10
) x
ORDER BY 1;
当然,您需要了解自己在做什么。在示例中,我选择了 10 个任意行,然后按第一列对它们进行排序。
您可以连续使用多层子查询或多个 CTE。
与 CTE 相同的示例:
WITH x AS (
SELECT *
FROM tbl
LIMIT 10
)
SELECT *
FROM x
ORDER BY 1;
对于简单的查询,子查询通常更快,CTE 提供额外的功能(例如在不同查询级别的多个地方重用相同的 CTE)。
还有更多方法——这里展示了一些方法,但还有第二种方法,如果你想在处理结束时移动函数调用,那么只需将 COST 设置为更高的值。自定义函数的默认值为 100,但您可以设置更高的值。
CREATE OR REPLACE FUNCTION public.test()
RETURNS integer
LANGUAGE plpgsql
IMMUTABLE COST 1000 -- very expensive function
AS $function$
declare i int;
declare j int;
begin
i := 1;
while i < 10000 loop
j := 1;
while j < 1000 loop
j := j + 1;
end loop;
i := i + 1;
end loop;
return i;
end;
$function$
如果没有 CTE(其他人已经解释过),您能做的最好的事情就是关闭某些类型的操作。这通常被认为是危险的并且是不得已而为之的方法,因为它通常指向数据库中的错误(即缺少索引、没有足够的清理、分析采样太低)或 PostgreSQL 代码中的错误。
但如果你想尝试一下,请查看“enable_seqscan”和其他设置,参见例如PostgreSQL 文档。