暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

PL/pgSQL 性能提升之二预加载

飞象数据 2018-11-23
750


背景

客户应用大量存储过程,并且创建连接后每次只调用一个函数,获得结果关闭连接,也就是大量短连接场景。为了最大限度的提高最大并发数与TPS,我们做了很多尝试。

PL/pgSQL引擎介绍

PostgreSQL 存储过程引擎设计非常先进,预留的接口可以实现非常丰富的语言支持,我们熟知的包括:C、PL/pgSQL、Python、Perl,还有非官方的 Java、PHP、JavaScript 等等。PL/pgSQL是最常用的官方过程语言,性能虽然无法与C语言相比,但胜在开发效率高,有测试表明它比其他几种官方语言引擎要快得多。为最大可能的提高函数调用的吞吐量,飞象数据对函数引擎进行了深入细致的分析,并且做了大量尝试和改进。外部模块加载官方自带或者我们自定义的模块在使用前,PG调用 load_external_function(src/backend/utils/fmgr/dfmgr.c) 进行载入:

    for (file_scanner = file_list;
         file_scanner != NULL &&         strcmp(libname, file_scanner->filename) != 0;
         file_scanner = file_scanner->next)
        ;    if (file_scanner == NULL)
    {
复制

如果模块对应的库文件尚未载入,依次执行载入(pg_dlopen)、校验(magic_func)、初始化(_PG_init)。

初始化(_PG_init)

载入和校验比较简单,是一个相对固定的开销;初始化部分相对复杂,并且不同模块会完全不同,以PL/pgSQL为例包括:1、参数注册2、哈希表创建3、回调函数注册

PL/pgSQL 函数执行过程首先找到引擎入口函数:

flying=# \df+ plpgsql_call_handlerList of functions
-[ RECORD 1 ]-------+---------------------
Schema              | pg_catalog
Name                | plpgsql_call_handler
Result data type    | language_handler
Argument data types |
Type                | normal
Volatility          | volatile
Parallel            | unsafe
Owner               | quanzl
Security            | invoker
Access privileges   |
Language            | c
Source code         | plpgsql_call_handler
Description         |
复制

引擎的执行入口函数并没有什么特别,也只是一个 C 语言实现的函数而已。而后,函数信息传递给 plpgsql_call_handler 做解释执行(参见 PL/pgSQL 性能提升之一预编译)。预加载PG使用过程中我们已经遇到过很多要求预加载的例子,比如:pldebugger、plprofiler,它们都要求写在 shared_preload_libraries,在数据库启动时载入和初始化。通过源代码可以看到,预加载模块与其它模块的加载过程是一样的。如果我们在 shared_preload_libraries 中添加 plpgsql,fork出来的新后端进程第一次调用函数时不再需要初始化,尤其在短连接场景下应该会有明显重用作用。实测pgbench 参数 -c 4 -j 4 -C

修改前

duration: 600 s
number of transactions actually processed: 537207
latency average = 4.468 ms
tps = 895.338221 (including connections establishing)
tps = 2497.664396 (excluding connections establishing)
复制

修改后

duration: 600 s
number of transactions actually processed: 666096
latency average = 3.603 ms
tps = 1110.153868 (including connections establishing)
tps = 4741.567239 (excluding connections establishing)
复制

结论短连接预加载 plpgsql 模块,在我们的测试case中可以得到一倍左右的性能提升。对于C 语言实现的模块,同样场景下可以同样处理来获得性能提升。

敬请关注飞象数据

文章转载自飞象数据,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论