Postgresql 将now()作为参数传递到函数中时如何计算

Postgresql 将now()作为参数传递到函数中时如何计算,postgresql,postgresql-10,query-planner,Postgresql,Postgresql 10,Query Planner,我有一个表,它是在带有时区字段的时间戳上进行范围分区的。我非常惊讶地发现,以下where条件导致计划者查询分区中的每个“子”表: WHERE reading_time > (now() - '72:00:00'::interval) 据我所知,planner不知道在执行时now()将是什么,因此它生成计划来查询每个子表。这是可以理解的,但这首先违背了设置分区的目的!如果我发布reading_time>'2018-03-31',它将只对包含符合这些条件的数据的表进行索引扫描 如果我创建以下

我有一个表,它是在带有时区字段的时间戳上进行范围分区的。我非常惊讶地发现,以下where条件导致计划者查询分区中的每个“子”表:

WHERE reading_time > (now() - '72:00:00'::interval)
据我所知,planner不知道在执行时now()将是什么,因此它生成计划来查询每个子表。这是可以理解的,但这首先违背了设置分区的目的!如果我发布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())

now()何时计算?或者,换句话说,文字时间值(例如2018-03-31 1:01:01+5)是否传递到函数中?如果是文本值,那么Postgres只查询相应的子表,对吗?但是如果它在函数中计算now(),那么我回到扫描每个子表的索引的计划。似乎很难看到规划者在函数中做什么。对吗?

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

PostgreSQL无法在计划时计算
now()
,因为无法知道语句何时执行。计划可以无限期地保留

如果使用
now()
作为参数调用函数,将在函数调用时对其进行计算

如果在涉及函数内分区表的SQL语句中使用参数(以便缓存计划),则可能会发生两种情况:

  • PostgreSQL决定在第五次执行查询后切换到通用计划。这样就不能进行分区修剪

  • PostgreSQL决定坚持使用自定义计划,以便进行分区修剪

  • 人们会假设通常会选择第二个选项,但要找到答案,可以使用
    auto\u explain
    查看实际使用的计划


    使用动态SQL可能是一个好主意,这样查询总是使用当前参数值重新规划,并且一定会使用分区修剪。

    感谢您花时间响应。因此,在我的PL/pgSQL函数的开头使用以下命令就足够了:
    在intime中执行'select now()'?不,这不会有什么区别,因为该值在计划时也是未知的。您应该使用动态SQL(
    EXECUTE
    )来确保从不使用通用计划,并且您总是从分区的约束排除中获益。