我有一个表,它是按带有时区字段的时间戳进行范围分区的。我非常惊讶地发现以下 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 语句中使用参数(因此计划被缓存),则可能会发生两种情况:
PostgreSQL 决定在第五次执行查询后切换到通用计划。那么就不能进行分区修剪。
PostgreSQL 决定坚持使用自定义计划,以便进行分区修剪。
人们会假设通常会选择第二个选项,但要找出您可以使用auto_explain
查看实际使用的计划。
使用动态 SQL 可能是一个好主意,以便始终使用当前参数值重新规划查询,并且肯定会使用分区修剪。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)