PostgreSQL 的一大特点是它的可扩展性。我的同事和高级PostgreSQL开发者Ibar在博客上发表了关于开发具有更广泛的功能(包括回调功能)的扩展的博客。在这个博客文章,我试图解决一个完整的新手用户谁从来没有尝试过,但想开发一个简单的函数与业务逻辑。在博客文章的结尾,我想通过执行简单的基准测试来说明函数的轻量级程度,这是可重复的,应该作为最终用户为什么要进行此类开发的有力理由。

通常,PostgreSQL 和扩展开发人员使用 PostgreSQL 源生成。对于新手用户,这可能不需要。相反,为 Linux 发行版提供的开发/开发包就足够了。假设您已经安装了 PostgreSQL,以下步骤可以为您提供所需的其他开发库。

在乌本图/德比亚

$ sudo apt install postgresql-server-dev-11

在 RHEL/CentOS 上

sudo yum install postgresql11-devel

下一步是将 PostgreSQL 二进制路径添加到您的环境中,以确保 pg_config 位于路径中5雷姆;边距顶部: 1.5rem;字体系列:《ITC 章程》;无衬线;字体样式:正常;字体变异连字:正常;字体-变量-大写:正常;字体重: 400;字母间距:正常;孤儿: 2;文本对齐:开始;文本缩进: 0px;文本转换:无;空白:正常;寡妇: 2;字间距: 0px;-webkit-文本-描边宽度:0px;背景色: rgb (255, 255, 255);文字装饰风格:首字母;文本装饰颜色:首字母;”*上述路径可能因环境而异。

请确保在未指定路径的情况下执行 pg_config:

$ pg_config

PostgreSQL 安装为扩展提供了一个构建基础结构,称为 PGXS,因此只需根据已安装的服务器即可构建简单的扩展模块。它自动执行简单服务器扩展模块的常见生成规则。

$ pg_config --pgxs
/usr/lib/postgresql/11/lib/pgxs/src/makefiles/pgxs.mk

现在,让我们创建一个目录来开发。我将开发一个简单的扩展,addme,一个函数,addme,添加两个数字。

$ mkdir addme

现在,我们需要创建一个 Makefile,它生成扩展。幸运的是,我们可以使用所有的PGXS宏。

MODULES = addme
EXTENSION = addme
DATA = addme--0.0.1.sql
PG_CONFIG = pg_config
PGXS := $(shell $(PG_CONFIG) --pgxs)
include $(PGXS)

现在,我们需要一个包含以下内容的控制文件 addme.control:

comment = 'Simple number add function'
default_version = '0.0.1'
relocatable = true
module_pathname = '$libdir/addme'

我们可以在 C 中准备函数,这将添加 2 个整数:

#include "postgres.h"
#include "fmgr.h"

PG_MODULE_MAGIC;

PG_FUNCTION_INFO_V1(addme);

Datum
addme(PG_FUNCTION_ARGS)
{
int32 arg1 = PG_GETARG_INT32(0);
int32 arg2 = PG_GETARG_INT32(1);

PG_RETURN_INT32(arg1 + arg2);
}

在此阶段,目录中只有 3 个文件。

$ ls
addme.c addme.control Makefile

现在,我们可以制作文件:

$ make

将以下内容添加到此文件中:

CREATE OR REPLACE FUNCTION
addme(int,int) RETURNS int AS 'MODULE_PATHNAME','addme'
LANGUAGE C STRICT;

并安装扩展:

$ sudo make install

现在,我们可以继续创建扩展并对其进行测试:

postgres=# create extension addme;
CREATE EXTENSION
postgres=# select addme(2,3);
addme
-------
5
(1 row)

与任何函数一样,我们可以在针对多个元数的查询中使用它。

postgres=# select 7||'+'||g||'='||addme(7,g) from generate_series(1,10) as g;
?column?
----------
7+1=8
7+2=9
7+3=10
7+4=11
7+5=12
7+6=13
7+7=14
7+8=15
7+9=16
7+10=17
(10 rows)

性能基准测试

select 1+2;


2. PLpgSQL 功能如下

CREATE FUNCTION addmepl(a integer, b integer)
 RETURNS integer
as $$ 
BEGIN
  return a+b;
END;
$$ LANGUAGE plpgsql;

对于此测试/基准,我将调用函数一百万次!

SQL + 运算符

time psql -c "select floor(random() * (100-1+1) + 1)::int+g from generate_series(1,1000000) as g" > out.txt

C 函数调用

$ time psql -c "select addme(floor(random() * (100-1+1) + 1)::int,g) from generate_series(1,1000000) as g" > out.txt

PL 函数调用

$ time psql -c "select addmepl(floor(random() * (100-1+1) + 1)::int,g) from generate_series(1,1000000) as g" > out

5雷姆;边距顶部: 1.5rem;字体系列:《ITC 章程》;无衬线;字体样式:正常;字体变异连字:正常;字体-变量-大写:正常;字体重: 400;字母间距:正常;孤儿: 2;文本对齐:开始;文本缩进: 0px;文本转换:无;空白:正常;寡妇: 2;字间距: 0px;-webkit-文本-描边宽度:0px;背景色: rgb (255, 255, 255);文字装饰风格:首字母;文本装饰颜色:首字母;”*我已针对每个案例执行过 6 次测试,并列出如下。

测试运行
Performance by language

按语言表示的性能

Performance by language

平均运行时间

正如我们所看到的,内置”+”运算符和扩展中的自定义 C 函数的性能所花的时间最少,性能几乎相同。但是 PLpgSQL 函数调用很慢,并且显示相当大的开销。希望这能说明为什么那些大量使用的函数需要编写为本机 C 扩展名。

Comments are closed.