Performance 为什么快速函数在任何函数中都会变慢?
我有一个返回整数数组的函数。如果我打电话:Performance 为什么快速函数在任何函数中都会变慢?,performance,postgresql,Performance,Postgresql,我有一个返回整数数组的函数。如果我打电话: select getmun_gaz(12554) 它在33毫秒内返回一个“整数[]”: {1547,1564} 与我得到的结果完全相同: select array[1547,1564] 相同的类型(整数[]),相同的值({15471564}),只有轻微的时间差。那么,为什么这会立即生效: select * from loc where id = any(array[1547,1564]) 但这需要2分钟以上 select * from loc
select getmun_gaz(12554)
它在33毫秒内返回一个“整数[]”:
{1547,1564}
与我得到的结果完全相同:
select array[1547,1564]
相同的类型(整数[]),相同的值({15471564}),只有轻微的时间差。那么,为什么这会立即生效:
select *
from loc
where id = any(array[1547,1564])
但这需要2分钟以上
select *
from loc
where id = any(getmun_gaz(12554))
如果需要,我将发布函数的内容和表的结构。这个数据来源的表格确实很大,但这在开始时没有什么区别,那么为什么最终会这样呢
职能:
CREATE OR REPLACE FUNCTION getmun_gaz(gaz_id integer)
RETURNS integer[] AS
$BODY$
with recursive locpais as (
select l.id, l.nome, l.tipo tid, lt.tipo, lp.pai, 1 as profund
from loc l
left join locpai lp on lp.loc = l.id
left join loctipo lt on lt.id = l.tipo
where l.id = gaz_id
union
select l.id, l.nome, l.tipo tid, lt.tipo, lp.pai, profund+1
from loc l
left join locpai lp on lp.loc = l.id
left join loctipo lt on lt.id = l.tipo
join locpais p on (l.id = p.pai)
)
select array_agg(id) from locpais
where tid = 8
$BODY$
LANGUAGE sql VOLATILE
COST 100;
如果需要,我将稍后添加表结构。现在得走了。第二个函数的问题是,如果函数不是不可变的db需要计算每行的值
与
any(数组[15471564])不同的是,
是一个常量。第二个数组的问题是,如果函数不是不可变的db需要为每一行计算他的值
与
any(数组[15471564])不同的是,
是一个常量。这是因为函数的
将函数声明为VOLATILE会告诉Postgres它有副作用,并且/或者每次调用它时它的值都会改变(例如,random()
)。这意味着在您的查询中,Postgres必须为loc
表中的每一行调用一次,并且不能使用id
上的索引来加快速度
如果您的函数只包含
SELECT
s,而没有调用其他VOLATILE
函数,则可以将其声明为稳定
。这告诉Postgres,当在一个查询中多次调用时,结果将保持不变;查询计划器现在可以在开始时调用它一次,并为每个id
比较重复使用该值,还可以通过使用索引优化大部分比较。这是因为函数的
将函数声明为VOLATILE会告诉Postgres它有副作用,并且/或者每次调用它时它的值都会改变(例如,random()
)。这意味着在您的查询中,Postgres必须为loc
表中的每一行调用一次,并且不能使用id
上的索引来加快速度
如果您的函数只包含
SELECT
s,而没有调用其他VOLATILE
函数,则可以将其声明为稳定
。这告诉Postgres,当在一个查询中多次调用时,结果将保持不变;查询计划器现在可以在开始时调用它一次,并为每个id
比较重复使用该值,还可以通过使用索引优化大部分比较。什么是getnum\u gaz()
?是的,您应该发布该函数,因为这里当然没有人知道其中包含什么。尝试将您的函数声明为稳定的
或不可变的
,看起来您解决了它,@Abelisto。将此作为答案发布,如果有效,绿色复选标记是您的。@Rodrigo这里似乎已经有了正确的答案:)只需选择更适合您功能的开关(它必须是稳定的IMO)。什么是getnum_gaz()
?是的,您应该发布该函数,因为这里当然没有人知道其中包含什么。尝试将您的函数声明为稳定的
或不可变的
,看起来您解决了它,@Abelisto。将此作为答案张贴,如果有效,绿色复选标记是您的。@Rodrigo这里似乎已经有了正确的答案:)只需选择更适合您功能的开关(它必须是稳定的IMO)。为什么要整张表?getmun_gaz(12554)只返回两个值,速度非常快!在底层逻辑中有一些东西我仍然没有得到。是的,我认为你在比较不同的东西,问题是如果你的函数不是INMMUTABLE,db必须为每一行计算它。相反,array[]
是一个常量。为什么要整张表?getmun_gaz(12554)只返回两个值,速度非常快!在底层逻辑中有一些东西我仍然没有得到。是的,我认为你在比较不同的东西,问题是如果你的函数不是INMMUTABLE,db必须为每一行计算它。相反,array[]
是一个常量。