现在如何评估()作为参数传递到函数时



i有一个表格在时间戳上分区的表格。我很惊讶地发现,以下条件导致计划者在分区中查询每个"孩子"表:

WHERE reading_time > (now() - '72:00:00'::interval)

我了解到,计划者不知道现在((在执行时会是什么,因此它生成了查询每个子表的计划。这是可以理解的,但这首先是设置分区的目的!如果我发布了Reading_time>'2018-03-31',它将仅执行索引扫描具有符合这些条件的数据的表。

如果我创建以下功能会发生什么情况

CREATE OR REPLACE FUNCTION public.last_72hours(in_time timestamp with time zone)
   Select * from precip where reading_time > (in_time - '72:00:00'::interval)
   --the function will then do work on the returned rows
END;

然后我可以用

调用该功能
SELECT last_72hours(now())

现在((什么时候进行评估?或者,换句话说,字面时间值(例如,2018-03-31 1:01:01 5(是否会传递到该函数中?如果是字面价值,那么Postgres仅查询适当的子表,对吗?但是,如果现在正在评估该功能内部((,那么我会回到扫描每个子表索引的计划。似乎没有什么容易看到计划者在功能中所做的事情。这是正确的吗?

这里有几个问题;我会尽力回答所有这些。

PostgreSQL无法在计划时评估now(),因为无法知道何时执行语句。计划可以无限的时间保存。

如果将now()称为参数的函数,将在函数调用时进行评估。

如果您在涉及函数内的分区表的SQL语句中使用参数(因此,计划被缓存(,则可能发生两件事:

  1. PostgreSQL决定在查询第五次执行后切换到通用计划。然后不可能进行分区修剪。

  2. PostgreSQL决定坚持自定义计划,以便进行分区修剪。

一个人通常会选择第二个选项,但是要找出您可以使用auto_explain查看实际使用的计划。

使用动态SQL可能是一个好主意,以便始终将查询重新粘贴到当前参数值中,并且可以使用分区修剪。

最新更新