PGVector(向量检索)

PGVector是一个高效的向量数据库插件,支持多种向量计算算法和数据类型,同时还能够高效存储与查询以向量表示的AI Embedding。本文档将为您介绍PGVector的背景、原理、使用方法及其他相关信息。

背景信息

随着数据科学和机器学习等技术的迅速发展,向量计算已经成为了大数据领域中最常见的计算任务之一。PolarDB PostgreSQL版(兼容Oracle)作为一种广泛使用的关系型数据库,结合PGVector插件后通过自定义的数据类型和存储方法,使得高维向量计算变得更加高效快速。

说明

数据库内部使用高维度(包括主流文本嵌入模型)存储表示输入输出的场景,PGVector插件最高支持16000维度

前提条件

支持的PolarDB PostgreSQL版(兼容Oracle)的版本如下:

  • Oracle语法兼容 2.0(内核小版本2.0.14.9.0及以上)

  • Oracle语法兼容 1.0(内核小版本1.1.35及以上)

说明

您可通过如下语句查看PolarDB PostgreSQL版(兼容Oracle)的内核小版本号:

SHOW polar_version;

注意事项

  • PX支持通过sort遍历高维向量。

  • PX不支持索引查询。

原理介绍

PGVector的索引算法是IVFFlat(同pase插件的向量算法)。IVFFlat是一种基于倒排索引的近似最近邻搜索算法,可以用于高效地查询向量之间的相似度。它将向量空间分为若干个划分区域,每个区域都包含一些向量,并创建倒排索引,用于快速地查找与给定向量相似的向量。

IVFFlat是IVFADC算法的简化版本,适合于召回精度要求高,但对查询耗时要求不严格(100ms级别)的场景。相比其他算法,IVFFlat算法具有高召回率、高精度、算法和参数简单、空间占用小的优势。

PGVector插件的实现基于PolarDB PostgreSQL版(兼容Oracle)的扩展机制,利用C语言编写实现多种向量计算算法和数据类型。其中插件算法的具体流程如下:

  1. 高维空间中的点基于隐形的聚类属性,按照K-Means等聚类算法对向量进行聚类处理,使得每个类簇有一个中心点。

  2. 检索向量时首先遍历计算所有类簇的中心点,找到与目标向量最近的n个类簇中心。

  3. 遍历计算n个类簇中心所在聚类中的所有元素,经过全局排序得到距离最近的k个向量。

使用指南

  • PGVector插件可以顺序及索引检索高维向量,示例列出了简单使用方法。

  • 召回率和性能介绍。

    PGVector插件在0.5.0版本前使用的IVFFlat索引构建速度快,相比于无任何索引能够提升一定的查询性能,但召回率表现一般,也会消耗一定的内存。新增的HNSW索引在召回率和性能上都有更加优秀的表现,但索引构建速度更慢,内存使用量更高。在使用向量索引来查询向量数据时,往往需要在性能与召回率两个维度上权衡利弊,这里介绍两种提升召回率的索引参数配置方法。

    • HNSW

      m:表示在每个索引元素之间存在多少双向链接(或路径)。默认值为16,取值范围为2~100。将该值设置为一个较高的数量,可以增加召回量。但也会显著增加索引生成时间,并可能影响查询性能。

      ef_construction:表示在索引中添加元素时,需要检查的近邻数。默认值为64,取值范围为4~100。增加该值可以增加召回量,但是会增加索引构建时间。该值必须至少是m的两倍。

      CREATE TABLE vecs (id int PRIMARY KEY, embedding vector(1536));
      CREATE INDEX ON vecs USING hnsw(embedding vector_l2_ops) WITH (m=16, ef_construction=64);

      必须指定使用HNSW索引的操作符类。例如,使用HNSW索引的余弦,可以使用如下命令:

      CREATE INDEX ON vecs USING hnsw(embedding vector_cosine_ops);

      可以先选择默认的索引构建配置项来优化构建时间。如果没有得到数据集的预期召回量,先增加ef_construction值,再调整m值。可以通过设置较大的hnsw.ef_search值来增加查询召回,例如,设置为100,值越大往往召回越高。

    • IVFFlat

      listsPGVector采样表中所有向量的聚类中心数量。

      CREATE INDEX ON vecs USING ivfflat(embedding) WITH (lists=100);

关于索引和更多的参数方法介绍可以参考开源代码的README模块。

示例

  1. 创建插件。

    CREATE EXTENSION vector;
  2. 创建表。

    CREATE TABLE t (val vector(3));
  3. 插入数据。

    INSERT INTO t (val) VALUES ('[0,0,0]'), ('[1,2,3]'), ('[1,1,1]'), (NULL);
  4. 创建向量索引。

    CREATE INDEX ON t USING ivfflat (val vector_ip_ops) WITH (lists = 1);
  5. 计算近似向量。

    SELECT * FROM t ORDER BY val <#> '[3,3,3]';

    返回结果如下:

       val
    ---------
     [1,2,3]
     [1,1,1]
     [0,0,0]
    (3 rows)
    说明
    • val vector_ip_ops表示需要创建索引的列名为val,并且使用PolarDB PostgreSQL版(兼容Oracle)中提供的向量操作符vector_ip_ops来计算向量之间的相似度。该操作符支持向量之间的点积、余弦相似度、欧几里得距离等计算方式。

    • WITH (lists = 1)表示使用的划分区域数量为1,这意味着所有向量都将被分配到同一个区域中。在实际应用中,划分区域数量需要根据数据规模和查询性能进行调整。

相关参考

向量的embedding过程请参考中国内地和国际文本embedding模型输出