PL/pgSQL存储过程DBeaver调用快但C#调用耗时极长求助
问题根因与解决方案
核心问题1:DELETE语句存在运算符优先级逻辑错误
你提供的存储过程中DELETE语句的WHERE条件未正确处理AND/OR的优先级:
-- 原错误写法 WHERE report_id = in_report_id AND column_name ilike 'customer%name' OR column_name ilike 'customer%number%' OR column_name ilike 'security address%' OR column_name ilike 'Initial Rate Term' OR column_name ilike 'Remaining Term (months)' OR column_name ilike 'Interest Only Amount (Part and Part)'
PostgreSQL中AND的运算优先级高于OR,上述条件实际执行逻辑为:
删除满足(
report_id = 传入值且字段名匹配customer%name)或者 字段名满足后面任意一个OR条件的所有行,完全不校验后几类条件的行所属的report_id。
如果你的datapipe_report_staging表数据量很大,这个语句会触发全表扫描+全表删除操作,自然会耗时极长。你在DBeaver中测试时大概率是手动给所有OR条件套了括号,或者测试环境表数据量极小,所以未触发性能问题。这也解释了为什么相同的C#调用方法对其他存储过程生效,其他存储过程没有触发这个逻辑错误。
修复方案
给所有OR条件套上括号,确保删除操作仅作用于指定的report_id:
DELETE FROM public.datapipe_report_staging WHERE report_id = in_report_id AND ( column_name ilike 'customer%name' OR column_name ilike 'customer%number%' OR column_name ilike 'security address%' OR column_name ilike 'Initial Rate Term' OR column_name ilike 'Remaining Term (months)' OR column_name ilike 'Interest Only Amount (Part and Part)' );
其他可能的性能问题
- 参数类型不匹配:检查
BuildStoredProcedureCall方法生成的参数类型,确保in_report_id、in_client_id参数的类型与PostgreSQL表的int4类型完全匹配,避免隐式类型转换导致report_id字段的索引失效。 - 缺少索引优化:给表添加以下索引提升查询性能:
-- 加速report_id过滤 CREATE INDEX IF NOT EXISTS idx_datapipe_report_staging_report_id ON public.datapipe_report_staging(report_id); -- 加速ilike模糊查询,需要先开启pg_trgm扩展 CREATE EXTENSION IF NOT EXISTS pg_trgm; CREATE INDEX IF NOT EXISTS idx_datapipe_report_staging_column_name_trgm ON public.datapipe_report_staging USING GIN (column_name gin_trgm_ops);
- 锁等待问题:检查调用存储过程时传入的
NpgsqlTransaction对应的事务是否存在长事务锁持有,可查询PostgreSQL的pg_locks系统视图确认是否有锁等待。
内容的提问来源于stack exchange,提问作者Denis Luiz
相关产品推荐
相关产品推荐

