为什么FOR <query> LOOP比基本查询慢得多?

时间:2017-03-14 11:18:32

标签: performance postgresql plpgsql postgresql-performance

我编写了非常简单的plpgsql函数,它从25mln行表中获取每一行并与prev行进行比较。如果两个兄弟行具有相等的"AOGUID"列,则返回它们。

CREATE or replace FUNCTION get_duplicate_zemli() RETURNS setof character varying AS $$
DECLARE
    each_zemla character varying;
    prev_zemla character varying;
BEGIN
    FOR each_zemla IN SELECT "AOGUID" FROM "Zemla" ORDER BY "AOGUID" LOOP
        if (prev_zemla = each_zemla) then
            return next each_zemla;
        end if;
        prev_zemla:= each_zemla;
    END LOOP;
END;
$$ LANGUAGE plpgsql;

据我了解,此函数应该在普通查询时间附近及时执行

SELECT "AOGUID" FROM "Zemla" ORDER BY "AOGUID" 

不幸的是,这不是真的。简单查询在一小时内执行,但函数在80小时内执行!

有人可以解释为什么plpgsql函数的执行速度比普通查询慢得多,以及如何提高性能?

PS:

explain SELECT "AOGUID" FROM "Zemla" ORDER BY "AOGUID" 
  

&#34;仅索引使用zemla_aoguid_not_unique扫描&#34; Zemla&#34;   (成本= 0.56..3336281.02行= 25852488宽度= 37)&#34;

2 个答案:

答案 0 :(得分:1)

也许我误读了您的查询,但您不只是在识别在“Zemla”中出现多次的任何AOGUID条目吗?这不能作为单个分组查询完成吗?

SELECT "AOGUID" FROM "Zemla"
GROUP BY "AOGUID"
HAVING COUNT(*) > 1
ORDER BY "AOGUID"

答案 1 :(得分:0)

检查这种qry的费用:

explain with pre94 as (
  SELECT "AOGUID", lag("AOGUID") over (ORDER BY "AOGUID") = "AOGUID" test_eq FROM "Zemla"
) 
select "AOGUID" from pre94 where test_eq

我相信窗口功能可以帮助你完成比自己创建的功能更好的任务。

如果您使用9.4 or later

,也可以使用FILTER减少qry