PostgreSQL【应用 03】Docker部署的PostgreSQL扩展SQL之C语言函数(编写、编译、载入)计算向量余弦距离实例分享

本文涉及的产品
云原生数据库 PolarDB MySQL 版,通用型 2核8GB 50GB
云原生数据库 PolarDB PostgreSQL 版,标准版 2核4GB 50GB
简介: PostgreSQL【应用 03】Docker部署的PostgreSQL扩展SQL之C语言函数(编写、编译、载入)计算向量余弦距离实例分享

通过使用 PostgreSQL 的 C 函数接口,我们可以编写用 C 语言实现的函数,并将其集成到数据库中。这些函数可以在 SQL 查询中像其他内置函数一样被调用,从而扩展 PostgreSQL 的功能。

C 函数在某些情况下可以提供比 SQL 函数更高的执行效率,因为它们可以直接访问底层系统资源并进行更高级的优化。通过使用 C 函数,我们可以在函数内部实现复杂的算法和逻辑,利用 C 语言的功能和库来提高执行效率。

环境说明:

# 此版本库可用
[root@tcloud ~]# docker -v
Docker version 20.10.13, build a224086
# 此版本不可用
[root@nodexxx ~]# docker -v
Docker version 1.13.1, build 7d71120/1.13.1

注意:Docker version 1.13.1无法使用。

1.准备

1.1 开发文档

-- 查询数据库版本
SELECT "version"()
-- PostgreSQL 12.12 (Debian 12.12-1.pgdg110+1) on x86_64-pc-linux-gnu, compiled by gcc (Debian 10.2.1-6) 10.2.1 20210110, 64-bit

根据数据库的版本查看文档:

英文:PostgreSQL: Documentation: 12: 37.10. C-Language Functions

中文:37.10. C 语言函数 (postgres.cn)

1.2 工具安装

# 避免报错1 bash: cc: command not found
# 未 update 可能会报错 E: Unable to locate package gcc
apt-get update
apt-get install gcc
# 避免报错2
functionNameFile.c:1:10: fatal error: postgres.h: No such file or directory
    1 | #include "postgres.h"
      |          ^~~~~~~~~~~~
compilation terminated.
# 根据版本进行安装【必备】
apt-get install postgresql-server-dev-12
# 报错
postgresql-server-dev-12 : Depends: llvm-11-dev but it is not installable

2.开始

2.1 编写C语言函数

创建一个新的文件,例如 cosine_distance_c.c,并添加以下内容:

#include "postgres.h"
#include "fmgr.h"
#include "math.h"
#include "utils/array.h"
#include "utils/float.h"
PG_MODULE_MAGIC;
PG_FUNCTION_INFO_V1(cosine_distance_c);
Datum cosine_distance_c(PG_FUNCTION_ARGS)
{
    ArrayType *arr1;
    arr1  = PG_GETARG_ARRAYTYPE_P(0);
    ArrayType *arr2;
    arr2 = PG_GETARG_ARRAYTYPE_P(1);
    int num_elems1, num_elems2;
    int16 elmlen;
    bool elmbyval, elmIsNull;
    Datum *elems1, *elems2;
    float8 sum_xy = 0.00000;
    float8 sum_x2 = 0.00000;
    float8 sum_y2 = 0.00000;
    float8 result;
    int i;
    deconstruct_array(arr1, 701, 8, FLOAT8PASSBYVAL, 'd', &elems1, NULL, &num_elems1);
    deconstruct_array(arr2, 701, 8, FLOAT8PASSBYVAL, 'd', &elems2, NULL, &num_elems2);
    if (num_elems1 != num_elems2)
        ereport(ERROR, (errmsg("Array lengths are not equal")));
    for (i = 0; i < num_elems1; i++)
    {
        sum_xy = sum_xy +  DatumGetFloat8(elems1[i]) * DatumGetFloat8(elems2[i]);
        sum_x2 = sum_x2 +  DatumGetFloat8(elems1[i]) * DatumGetFloat8(elems1[i]);
        sum_y2 = sum_y2 +  DatumGetFloat8(elems2[i]) * DatumGetFloat8(elems2[i]);
    }
    if (sum_x2 == 0.0 || sum_y2 == 0.0)
        ereport(ERROR, (errmsg("One or both arrays have zero magnitude")));
    result = sum_xy / (sqrt(sum_x2) * sqrt(sum_y2));
    pfree(elems1);
    pfree(elems2);
    PG_RETURN_FLOAT8(result);
}

2.2 编译和链接动态载入的函数

Linux环境:

# 创建PIC的编译器标志是-fpic。创建一个共享库的编译器标志是-shared。
cc -fPIC -c funcs.c
cc -shared -o funcs.so funcs.o

实例使用 C 编译器将源代码编译为共享库,例如 cosine_distance_c.so

# 使用
cc -fPIC -I`pg_config --includedir-server` -c cosine_distance_c.c
cc -shared -o cosine_distance_c.so cosine_distance_c.o -I`pg_config --includedir-server` -lm
  1. 将共享库文件复制到 PostgreSQL 的共享库目录中:
cp cosine_distance_c.so `pg_config --libdir`/.
# 实际查询
root@a0e33689b846:/# pg_config --libdir
/usr/lib/x86_64-linux-gnu
  1. 在 PostgreSQL 中创建函数的定义:
-- 这里用到了 pg_config --libdir 查询到的目录
CREATE FUNCTION cosine_distance_c(float8[], float8[])
    RETURNS float8
    AS '//usr/lib/x86_64-linux-gnu/cosine_distance_c.so', 'cosine_distance_c'
    LANGUAGE C STRICT;

现在,你可以在 SQL 查询中使用 cosine_distance_c 函数来计算两个 numeric 数组之间的余弦距离,例如:

SELECT cosine_distance_c(ARRAY[1.0, 2.0, 3.0], ARRAY[4.0, 5.0, 6.0]);

注意:上述示例是一个简化的实现,它假设传入的两个数组参数都是 numeric 类型的一维数组。在实际应用中,你可能需要进行更多的参数校验和错误处理,并支持更复杂的数组类型和维度。

相关实践学习
使用PolarDB和ECS搭建门户网站
本场景主要介绍如何基于PolarDB和ECS实现搭建门户网站。
阿里云数据库产品家族及特性
阿里云智能数据库产品团队一直致力于不断健全产品体系,提升产品性能,打磨产品功能,从而帮助客户实现更加极致的弹性能力、具备更强的扩展能力、并利用云设施进一步降低企业成本。以云原生+分布式为核心技术抓手,打造以自研的在线事务型(OLTP)数据库Polar DB和在线分析型(OLAP)数据库Analytic DB为代表的新一代企业级云原生数据库产品体系, 结合NoSQL数据库、数据库生态工具、云原生智能化数据库管控平台,为阿里巴巴经济体以及各个行业的企业客户和开发者提供从公共云到混合云再到私有云的完整解决方案,提供基于云基础设施进行数据从处理、到存储、再到计算与分析的一体化解决方案。本节课带你了解阿里云数据库产品家族及特性。
目录
相关文章
|
3月前
|
SQL 人工智能 数据挖掘
如何在`score`表中正确使用`COUNT`和`AVG`函数?SQL聚合函数COUNT与AVG使用指南
本文三桥君通过score表实例解析SQL聚合函数COUNT和AVG的常见用法。详解COUNT(studentNo)、COUNT(score)、COUNT()的区别,以及AVG函数对数值/字符型字段的不同处理,特别指出AVG()是无效语法。实战部分提供6个典型查询案例及结果,包含创建表、插入数据的完整SQL代码。产品专家三桥君强调正确理解函数特性(如空值处理、字段类型限制)对数据分析的重要性,帮助开发者避免常见误区,提升查询效率。
223 0
|
7月前
|
C语言
C语言中条件操作符的应用
最后,条件操作符是个超级英雄,但不是每个代码问题都需要一个超级英雄来解决。一定要在适当的时候适度的使用它,那么它将成为你的编程工具箱中的一件强力工具。
330 75
|
12月前
|
存储 缓存 算法
在C语言中,数据结构是构建高效程序的基石。本文探讨了数组、链表、栈、队列、树和图等常见数据结构的特点、应用及实现方式
在C语言中,数据结构是构建高效程序的基石。本文探讨了数组、链表、栈、队列、树和图等常见数据结构的特点、应用及实现方式,强调了合理选择数据结构的重要性,并通过案例分析展示了其在实际项目中的应用,旨在帮助读者提升编程能力。
343 5
|
12月前
|
存储 程序员 编译器
C 语言数组与指针的深度剖析与应用
在C语言中,数组与指针是核心概念,二者既独立又紧密相连。数组是在连续内存中存储相同类型数据的结构,而指针则存储内存地址,二者结合可在数据处理、函数传参等方面发挥巨大作用。掌握它们的特性和关系,对于优化程序性能、灵活处理数据结构至关重要。
|
12月前
|
存储 NoSQL 编译器
C 语言中指针数组与数组指针的辨析与应用
在C语言中,指针数组和数组指针是两个容易混淆但用途不同的概念。指针数组是一个数组,其元素是指针类型;而数组指针是指向数组的指针。两者在声明、使用及内存布局上各有特点,正确理解它们有助于更高效地编程。
|
12月前
|
网络协议 物联网 数据处理
C语言在网络通信程序实现中的应用,介绍了网络通信的基本概念、C语言的特点及其在网络通信中的优势
本文探讨了C语言在网络通信程序实现中的应用,介绍了网络通信的基本概念、C语言的特点及其在网络通信中的优势。文章详细讲解了使用C语言实现网络通信程序的基本步骤,包括TCP和UDP通信程序的实现,并讨论了关键技术、优化方法及未来发展趋势,旨在帮助读者掌握C语言在网络通信中的应用技巧。
308 2
|
12月前
|
机器学习/深度学习 算法 数据挖掘
C语言在机器学习中的应用及其重要性。C语言以其高效性、灵活性和可移植性,适合开发高性能的机器学习算法,尤其在底层算法实现、嵌入式系统和高性能计算中表现突出
本文探讨了C语言在机器学习中的应用及其重要性。C语言以其高效性、灵活性和可移植性,适合开发高性能的机器学习算法,尤其在底层算法实现、嵌入式系统和高性能计算中表现突出。文章还介绍了C语言在知名机器学习库中的作用,以及与Python等语言结合使用的案例,展望了其未来发展的挑战与机遇。
287 1
|
12月前
|
并行计算 算法 测试技术
C语言因高效灵活被广泛应用于软件开发。本文探讨了优化C语言程序性能的策略,涵盖算法优化、代码结构优化、内存管理优化、编译器优化、数据结构优化、并行计算优化及性能测试与分析七个方面
C语言因高效灵活被广泛应用于软件开发。本文探讨了优化C语言程序性能的策略,涵盖算法优化、代码结构优化、内存管理优化、编译器优化、数据结构优化、并行计算优化及性能测试与分析七个方面,旨在通过综合策略提升程序性能,满足实际需求。
353 1
|
12月前
|
存储 C语言 计算机视觉
在C语言中指针数组和数组指针在动态内存分配中的应用
在C语言中,指针数组和数组指针均可用于动态内存分配。指针数组是数组的每个元素都是指针,可用于指向多个动态分配的内存块;数组指针则指向一个数组,可动态分配和管理大型数据结构。两者结合使用,灵活高效地管理内存。
|
12月前
|
SQL 开发框架 .NET
突破T-SQL限制:利用CLR集成扩展RDS SQL Server的功能边界
CLR集成为SQL Server提供了强大的扩展能力,突破了T-SQL的限制,极大地拓展了SQL 的应用场景,如:复杂字符串处理、高性能计算、图像处理、机器学习集成、自定义加密解密等,使开发人员能够利用 .NET Framework的丰富功能来处理复杂的数据库任务。

热门文章

最新文章