我有一个返回整数数组的函数。如果我打电话:
select getmun_gaz(12554)
它返回一个'整数[]'在33毫秒:
{1547,1564}
我得到的结果完全相同:
select array[1547,1564]
相同类型(整数[]),相同的值({1547,1564}),只有微小的时差。那么,为什么这会立即起作用:
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;
如果需要,我稍后会添加表格结构。现在要走了。
答案 0 :(得分:3)
这是因为你的功能是volatility。
将函数声明为VOLATILE
告诉Postgres它有副作用,和/或每次调用它时它的值都会改变(例如random()
)。这意味着在您的查询中,Postgres必须为loc
表中的每一行调用一次,并且不能使用id
上的索引来加快速度。
如果您的函数仅包含SELECT
s,而没有调用其他VOLATILE
函数,则可以将其声明为STABLE
。这告诉Postgres在单个查询中多次调用时结果将保持不变;查询规划器现在可以在开始时调用它一次并重新使用每个id
比较的值,并且还可以通过使用索引来优化大多数这些比较。
答案 1 :(得分:2)
第二个问题是如果函数不是IMMUTABLE
db需要计算每行的值
与any(array[1547,1564])
不同的是常数。