为何在内部任何时候快速功能变慢?

时间:2016-03-02 20:40:36

标签: performance postgresql

我有一个返回整数数组的函数。如果我打电话:

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;

如果需要,我稍后会添加表格结构。现在要走了。

2 个答案:

答案 0 :(得分:3)

这是因为你的功能是volatility

将函数声明为VOLATILE告诉Postgres它有副作用,和/或每次调用它时它的值都会改变(例如random())。这意味着在您的查询中,Postgres必须为loc表中的每一行调用一次,并且不能使用id上的索引来加快速度。

如果您的函数仅包含SELECT s,而没有调用其他VOLATILE函数,则可以将其声明为STABLE。这告诉Postgres在单个查询中多次调用时结果将保持不变;查询规划器现在可以在开始时调用它一次并重新使用每个id比较的值,并且还可以通过使用索引来优化大多数这些比较。

答案 1 :(得分:2)

第二个问题是如果函数不是IMMUTABLE db需要计算每行的值

any(array[1547,1564])不同的是常数。