gpt4 book ai didi

postgresql - now() 在作为参数传递给函数时如何得到评估

转载 作者:行者123 更新时间:2023-11-29 13:15:33 25 4
gpt4 key购买 nike

我有一个按时间戳和时区字段进行范围分区的表。我很惊讶地发现以下 where 条件导致规划器查询分区中的每个“子”表:

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

据我所知,规划器不知道 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 语句中使用参数(因此计划被缓存),可能会发生两件事:

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

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

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

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

关于postgresql - now() 在作为参数传递给函数时如何得到评估,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49599047/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com