2016-03-02 60 views
1

我有一个函数返回一个整数数组。如果我打电话:为什么快速功能在ANY内部变慢?

select getmun_gaz(12554) 

它返回一个 '整数[]' 在33毫秒:

{1547,1564} 

完全相同的结果我得到:

select array[1547,1564] 

同类型(整数[]),相同的值({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

getnum_gaz()是什么?是的,你应该发布该功能,因为当然这里没有人知道它的内容。 – Pointy

+1

尝试声明你的函数为'STABLE'或'IMMUTABLE' [请阅读原因](http://www.postgresql.org/docs/9.5/static/sql-createfunction.html) – Abelisto

+0

看起来像你解决了它,@ Abelisto。发布这个作为答案,如果它的作品绿色复选标记是你的。 – Rodrigo

回答

3

这是因为你的函数的volatility

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

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

2

与第二个问题是如果未启用功能IMMUTABLE分贝需要计算其价值为每一行

在差异与any(array[1547,1564])是一个常数。

+0

为什么整张桌子? getmun_gaz(12554)只返回两个值,而且非常快!我仍然没有得到底层逻辑中的某些东西。 – Rodrigo

+1

是的,我想你是比较不同的东西,问题是如果你的功能isnt'不可变'分贝必须计算每行。相反'array []'是一个常量。 –