fra*_*ima 10 postgresql plpgsql database-performance query-performance postgresql-performance
我有这个过程,必须使用pl/pgsql进行一系列查询:
--process:
SELECT function1();
SELECT function2();
SELECT function3();
SELECT function4();
Run Code Online (Sandbox Code Playgroud)
为了能够在一次调用中执行所有操作,我创建了一个过程函数:
CREATE OR REPLACE FUNCTION process()
RETURNS text AS
$BODY$
BEGIN
PERFORM function1();
PERFORM function2();
PERFORM function3();
PERFORM function4();
RETURN 'process ended';
END;
$BODY$
LANGUAGE plpgsql
Run Code Online (Sandbox Code Playgroud)
问题是,当我总结每个函数自身所用的时间时,总计为200秒,而函数所process()
用的时间超过一个小时!
也许这是一个内存问题,但我不知道postgresql.conf
应该改变哪种配置.
DB在Debian 8中的PostgreSQL 9.4上运行.
Erw*_*ter 10
您评论说4个函数必须连续运行.因此,可以安全地假设每个函数都使用上一个函数修改过的表中的数据.那是我的主要嫌疑人.
任何Postgres函数都在外部上下文的事务中运行.因此,如果打包到另一个函数中,所有函数共享相同的事务上下 显然,每个人都可以看到对以前功能的数据的影响.(即使效果对其他并发事务仍然是不可见的.)但统计信息不会立即更新.
查询计划基于所涉及对象的统计信息.PL/pgSQL在实际执行之前不会计划语句,这对您有利.每个文件:
当每个表达式和SQL命令首先在函数中执行时,PL/pgSQL解释器使用SPI管理器的SPI_prepare函数解析并分析命令以创建预准备语句.
PL/pgSQL 可以缓存查询计划,但只能在同一个会话中(至少在第9.2+页中),只有在几次执行后才能显示相同的查询计划才能重复运行.如果您怀疑这对您来说是错误的,您可以使用动态SQL来解决它,每次都会强制执行一个新计划:
EXECUTE 'SELECT function1()';
Run Code Online (Sandbox Code Playgroud)
但是,我看到的最可能的候选者是导致查询计划较差的无效统计信息.函数内部的SELECT
/ PERFORM
statements(同样的东西)快速连续运行,autovacuum没有机会在一个函数和下一个函数之间启动和更新统计信息.如果一个函数实质上改变了下一个函数正在使用的表中的数据,则下一个函数可能将其查询计划基于过时的信息.典型示例:具有几行的表格中填充了数千行,但下一个计划仍然认为"小"表的顺序扫描速度最快.你说:
当我总结每个函数自身所用的时间时,总计是200秒,而函数process()所花费的时间超过一个小时!
什么确切地不"本身"是什么意思?您是在一次交易或个别交易中运行它们吗?甚至可能介于两者之间?这将允许autovacuum更新统计信息(通常相当快),并可能根据更改的统计信息导致完全不同的查询计划.
您可以使用auto-explain检查plpgsql函数内的查询计划
如果您能识别出这样的问题,可以ANALYZE
在语句之间强制执行.在它,只有几个SELECT
/ PERFORM
语句你也可以使用更简单的SQL函数,并完全避免计划缓存(但见下文!):
CREATE OR REPLACE FUNCTION process()
RETURNS text AS
$func$
SELECT function1();
ANALYZE some_substantially_affected_table;
SELECT function2();
SELECT function3();
ANALYZE some_other_table;
SELECT function4();
SELECT 'process ended'; -- only last result is returned
$func$ LANGUAGE sql;
Run Code Online (Sandbox Code Playgroud)
此外,只要我们没有看到被调用函数的实际代码,就可以有任意数量的其他隐藏效果.
示例:您可以使用SET LOCAL ...
一些配置参数来提高您的性能function1()
.如果在不影响其余事务的单独事务中调用.效果只持续到交易结束.但如果在一次交易中调用它也会影响其余的事务......
基本:
另外:事务累积锁定,这会锁定越来越多的资源,并可能导致与并发进程的摩擦增加.所有锁都在事务结束时释放.如果可能的话,最好在单独的事务中运行大函数,而不是包装在单个函数中(因此包含事务).最后一项与@klin和IMSoP已涵盖的内容有关.
归档时间: |
|
查看次数: |
6934 次 |
最近记录: |