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_c2 つの数値配列間のコサイン距離を計算できるようになりました。次に例を示します。

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

注: 上記の例は簡略化された実装であり、渡される両方の配列パラメーターが数値型の 1 次元配列であることを前提としています。実際のアプリケーションでは、より多くのパラメーターの検証とエラー処理を実行し、より複雑な配列の型と次元をサポートする必要がある場合があります。

おすすめ

転載: blog.csdn.net/weixin_39168541/article/details/131846430