创建 IVF 索引

本页面介绍了如何使用 AlloyDB for PostgreSQL 中的 IVF 索引,通过存储的嵌入生成索引和查询嵌入。如需详细了解如何存储嵌入,请参阅存储向量嵌入

准备工作

在开始创建索引之前,您必须完成以下前提条件。

创建 IVF 索引

原生 pgvector 支持通过索引编制进行近似最近邻搜索。AlloyDB 在这种支持的基础上增加了一个标量量化功能,您可以在创建索引时指定该功能。启用后,标量量化可以显著加快具有较大维度向量的查询的速度,并可以让您存储最多具有 8,000 个维度的向量。

如需对基于 pgvector 的索引启用标量量化,请将 IVF 指定为索引方法,并将 SQ8 指定为量化器:

CREATE INDEX INDEX_NAME ON TABLE
  USING ivf (EMBEDDING_COLUMN DISTANCE_FUNCTION)
  WITH (lists = LIST_COUNT, quantizer = 'QUANTIZER');

替换以下内容:

  • INDEX_NAME:要创建的索引的名称,例如 my-ivf-index。索引名称会在整个数据库中共享。确保每个索引名称对数据库中的每个表中都是唯一的。

  • TABLE:要向其中添加索引的表。

  • EMBEDDING_COLUMN:用于存储 vector 数据的列。

  • DISTANCE_FUNCTION:要与此索引一起使用的距离函数。请按以下方式之一操作:

    • L2 距离:vector_l2_ops

    • 内积:vector_ip_ops

    • 余弦距离:vector_cosine_ops

  • LIST_COUNT:要与此索引一起使用的列表的数量。如需详细了解如何确定此值,请参阅对 IVF 索引进行调优

  • QUANTIZER:要使用的量化器类型。

    设置为以下任一项:

    • SQ8:推荐。查询响应速度较快,但会导致一些召回率损失(这不会影响生产场景)。
    • FLAT:查询响应速度较慢,内存用量较高,但召回率损失可忽略不计。

    如需在使用 real[] 数据类型(而非 vector)的嵌入列上创建此索引,请将该列转换为 vector 数据类型:

CREATE INDEX INDEX_NAME ON TABLE
  USING ivf (CAST(EMBEDDING_COLUMN AS vector(DIMENSIONS)))'}} DISTANCE_FUNCTION)
  WITH (lists = LIST_COUNT, quantizer = 'SQ8');

DIMENSIONS 替换为嵌入列的维度宽度。如需详细了解如何查找维度,请参阅向量函数中的 vector_dims 函数。

如需查看索引编制进度,请使用 pg_stat_progress_create_index 视图:

SELECT * FROM pg_stat_progress_create_index;

phase 列会显示索引创建的当前状态,building postings 阶段指示索引创建即将完成。

如需对索引进行调优以实现目标召回率和 QPS 平衡,请参阅IVF 索引进行调优

运行查询

在将嵌入存储到数据库中并为其编制索引后,您可以开始使用 pgvector 查询功能进行查询。

如需查找嵌入向量的语义最近邻,您可以运行以下示例查询,其中设置了在创建索引期间使用的相同距离函数。

  SELECT * FROM TABLE
    ORDER BY EMBEDDING_COLUMN DISTANCE_FUNCTION_QUERY ['EMBEDDING']
    LIMIT ROW_COUNT

替换以下内容:

  • TABLE:包含要与文本进行比较的嵌入的表。

  • INDEX_NAME:要使用的索引的名称,例如 my-scann-index

  • EMBEDDING_COLUMN:包含存储的嵌入的列。

  • DISTANCE_FUNCTION_QUERY:要用于此查询的距离函数。根据创建索引时使用的距离函数,选择以下各项之一:

    • L2 距离:<->

    • 内积:<#>

    • 余弦距离:<=>

  • EMBEDDING:您要为其查找存储的语义最近邻的嵌入向量。

  • ROW_COUNT:要返回的行数。

    如果您只想获得单个最佳匹配项,请指定 1

如需详细了解其他查询示例,请参阅查询

您还可以使用 embedding() 函数将文本转换为向量。您可以将向量应用于某个 pgvector 最近邻运算符(适用于 L2 距离的 <->),以查找具有语义最相似的嵌入的数据库行。

由于 embedding() 会返回 real 数组,因此您必须明确将 embedding() 调用转换为 vector,以便将这些值与 pgvector 运算符结合使用。

后续步骤