PL / pgSQL性能分析

时间:2014-09-17 06:54:22

标签: performance postgresql profiling plpgsql

我想提高一些 PL / pgSQL 存储过程的性能(我使用PostgreSQL 9.3)。 我使用 pg_stat_statements 扩展来隔离和改进原子SQL语句,现在程序的大部分执行时间不再映射到SQL语句。换句话说,似乎我的瓶颈是语言的开销。

我的主程序在for循环中调用(在本例中为31478次) add_link()过程。 add_link()的总时间 21.7秒。每个 add_link()调用 calc_link_count(),总共 11.5秒(超出21.7)。 但是,最昂贵的SQL语句需要整体 1.5秒(超过21.7!)。

如何分析程序以更好地了解投入时间? 是否有用于映射瓶颈的分析工具?

谢谢!

在循环31478次中调用 add_link()的主要功能:

CREATE OR REPLACE FUNCTION validate_added_links() RETURNS SETOF linkwithvalidationresult AS
$BODY$
DECLARE
    link RECORD;
BEGIN

    FOR link IN (SELECT * FROM linktovalidate) LOOP
        PERFORM add_link(link.linkid, link.objid);
    END LOOP;

    RETURN QUERY SELECT * FROM linkwithvalidationresult;

END
$BODY$ 
LANGUAGE plpgsql VOLATILE COST 100;

add_link(),调用 calc_link_count()(总共21.7秒):

CREATE OR REPLACE FUNCTION add_link(link_id uuid, object_id uuid)
RETURNS void AS
$BODY$
DECLARE
    features_broken_count integer = -1;
    src_id uuid;
    dst_id uuid;
    linkschema_id uuid;
BEGIN

    -- Most expensive SQL statement - 1.6 seconds overall
    SELECT sourceobjectid,destinationobjectid,linkschemaid INTO src_id,dst_id,linkschema_id FROM link WHERE objid=link_id; 


    -- Calculate broken features count
    features_broken_count := (SELECT calc_link_count(src_id,dst_id,linkschema_id));

    ...
    ...
    ...
    ...

END;
$BODY$
LANGUAGE plpgsql VOLATILE
COST 100;
ALTER FUNCTION add_link(uuid, uuid)
OWNER TO postgres;

calc_link_count()程序(总计11.5秒):

CREATE OR REPLACE FUNCTION calc_link_count(src_id uuid, dst_id uuid, linkschema_id uuid)
RETURNS integer AS
$BODY$
DECLARE
    features_broken_count integer = 0;
BEGIN

IF (NOT EXISTS (SELECT 1 FROM groupmembercount WHERE groupid=src_id)) THEN

    features_broken_count := features_broken_count  + (SELECT COUNT(*) FROM
    (SELECT notallowedfeatures FROM linkschema_notallowedfeatures WHERE linkschema_objid=linkschema_id
    AND notallowedfeatures IN (
    SELECT features FROM featurespreset_features JOIN dleobjectderef ON featurespreset=featurespreset_objid WHERE objid=dst_id)) AS cnt);

    features_broken_count := features_broken_count  + (SELECT COUNT(*) FROM
    (SELECT requiredfeatures FROM linkschema_requiredfeatures WHERE linkschema_objid=linkschema_id
    AND requiredfeatures NOT IN (
    SELECT features FROM featurespreset_features JOIN dleobjectderef ON featurespreset=featurespreset_objid WHERE objid=dst_id)) AS cnt);

END IF;

RETURN features_broken_count;

END;
$BODY$
LANGUAGE plpgsql VOLATILE
COST 100;

0 个答案:

没有答案