我想提高一些 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;