

本文属于机器翻译版本。若本译文内容与英语原文存在差异，则一律以英文原文为准。

# 向量搜索概述
<a name="vector-search-overview"></a>

ElastiCache for Valkey 提供了索引、搜索和更新数十亿个高维向量嵌入的功能。借助向量搜索功能，您可以创建、维护和使用二级索引，实现高效且可扩展的搜索。每个向量搜索操作都应用于单个索引。索引操作仅应用于指定的索引。除索引创建和删除操作外，任何索引在任何时候均可执行任意数量的操作。在集群级别，可以同时对多个索引执行多个操作。

在本文档中，术语“键”、“行”和“记录”的含义相同，可以互换使用。同样，术语“列”、“字段”、“路径”和“成员”也可以互换使用。

`FT.CREATE` 命令可用于为具有指定索引类型的键子集创建索引。`FT.SEARCH` 对创建的索引执行查询，而 `FT.DROPINDEX` 删除现有索引和所有关联数据。没有用于添加、删除或修改索引数据的特殊命令。使用现有的 `HASH` 或 `JSON` 命令对索引中的键进行修改会自动更新索引。

**Topics**
+ [索引和 Valkey OSS 键空间](#indexes-keyspace)
+ [索引字段类型](#index-field-types)
+ [向量索引算法](#vector-index-algorithms)
+ [向量搜索安全](#vector-search-security)

## 索引和 Valkey OSS 键空间
<a name="indexes-keyspace"></a>

在 Valkey OSS 键空间子集的基础上构造和维护索引。每个索引的键空间由创建索引时提供的键前缀列表定义。前缀列表是可选的，如果省略前缀列表，则整个键空间将成为该索引的一部分。多个索引可以不受限制地选择不相交或不重叠的键空间子集。

索引还具有类型，并且仅涵盖具有匹配类型的键。目前仅支持 `JSON` 和 `HASH` 类型的索引。`HASH` 索引仅为前缀列表所涵盖的 `HASH` 键编制索引，同样，`JSON` 索引仅为其前缀列表所涵盖的 `JSON` 键编制索引。在索引的键空间前缀列表中，未指定类型的键将被忽略，并且也不会影响搜索操作。

当命令修改索引键空间内的键时，该索引就会更新。Valkey 会自动提取每个索引的已声明字段，并使用新值更新索引。更新过程包含三个步骤。第一步，修改 HASH 或 JSON 键并阻止发出请求的客户端。第二步在后台执行，更新包含修改后的键的每个索引。第三步，取消阻止客户端。因此，对于在与变更相同的连接上执行的查询操作，该更改会立即反映在搜索结果中。

索引的创建是一个多步骤过程。第一步是执行定义索引的 FT.CREATE 命令。成功执行创建命令后会自动启动第二步：回填。回填过程在后台线程中运行，并会扫描键空间，查找位于新索引前缀列表中的键。找到的每个键都会添加到索引中。最终，整个键空间都会接受扫描，完成索引创建过程。请注意，在回填过程运行时，允许对索引键进行变更并且没有任何限制，索引回填过程只有在所有键都正确编制索引后才会完成。在索引回填时，不允许尝试查询操作，否则回填终止并显示错误。FT.INFO 命令在“backfill\$1status”字段中返回回填过程状态。

## 索引字段类型
<a name="index-field-types"></a>

每个索引都有创建索引时声明的特定类型以及要索引到的字段（列）的位置。对于 `HASH` 键，位置是 `HASH` 中的字段名称。对于 `JSON` 键，位置是 JSON 路径描述。修改键时，系统会提取与已声明字段关联的数据，将其转换为声明的类型并存储在索引中。如果数据丢失或无法成功转换为声明的类型，则该字段将从索引中省略。有三种类型的字段，如下所述：
+ **向量字段**包含一个数字向量，也称为向量嵌入。向量字段可用于根据指定的距离指标（用于衡量相似度）来筛选向量。对于 `HASH` 索引，该字段应包含以二进制格式（小端序 IEEE 754）编码的整个向量。对于 `JSON` 键，路径应引用大小正确且填充数字的数组。请注意，当将 JSON 数组用作向量字段时，JSON 键中数组的内部表示形式会转换为所选算法所需的格式，从而减少内存消耗和精度。使用 JSON 命令进行的后续读取操作所产生值的精度会降低。
+ **数值字段**包含一个数字。数值字段可以与范围搜索运算符搭配使用。对于 `HASH`，字段应包含以固定或浮点数标准格式编写的数值 ASCII 文本。对于 `JSON` 字段，必须遵守 JSON 数字规则。无论键内的表示形式如何，字段都将转换为在索引中存储的 64 位浮点数。基础数字以浮点数形式存储并且有精度限制，因此适用于浮点数比较的常用规则对于数值字段也适用。
+ **标签字段**包含零个或多个标签值，编码为单个 UTF-8 字符串。对于标签字段，可以在查询时对标签值进行筛选，并且可以选择区分大小写或不区分大小写。字符串解析为使用分隔符（默认为英文逗号，但可更改）分隔的标签值，并删除前导和尾随空格。单个标签字段中可以包含任意数量的标签值。

## 向量索引算法
<a name="vector-index-algorithms"></a>

Valkey 支持两种向量索引算法：
+ **Flat** – Flat 算法是对索引中每个向量进行暴力线性处理，提供距离计算精度范围内的精确答案。由于索引采用线性处理，因此对于大型索引，此算法的运行时间可能非常长。扁平索引支持更高的摄取速度。
+ **分层可导航小世界（HNSW）**：HNSW 算法是一种替代方案，它能够提供近似最近向量匹配结果，从而极大程度缩短执行时间。该算法由 `M`、`EF_CONSTRUCTION` 和 `EF_RUNTIME` 三个参数控制。前两个参数在创建索引时指定，无法更改。`EF_RUNTIME` 参数的默认值在创建索引时指定，但之后可以在任何单独的查询操作中更改。这三个参数相互作用，在摄取和查询操作期间平衡内存和 CPU 消耗，并控制精确 KNN 搜索近似值的质量（称为查准率）。

在 HNSW 中，参数 M 控制每个节点可以连接的最大邻居数量，从而调整索引密度。较高的 M（例如 32 及以上）会生成更联通的图，从而提高召回率和查询速度，因为有更多的路径可以到达相关邻居。但是，这会增加索引大小和内存占用量，并且会减慢索引速度。较低的 M（例如 8 及以下）产生的 faster-to-build索引较小，内存使用量较低，但由于连接较少，召回率会降低，查询可能需要更长的时间。

参数 EF\$1construction 定义在构建索引时要评估多少个候选连接。较高的 EF\$1construction（例如 400 及以上）意味着索引器在选择邻居之前会考虑更多路径，从而生成一个在后续操作中能同时提升召回率和查询效率的图，但在构造过程中会降低索引速度并且会增加 CPU 和内存使用量。较低的 EF\$1construction（例如 64-120）可以加快索引速度并减少资源使用量，但是生成的图也会降低召回率和查询速度，即使将 EF\$1runtime 设置的较高也是如此。

最后，EF\$1runtime 控制查询过程中的搜索范围，决定运行时探索的候选邻居数量。将该值设置得较高可提高召回率和准确率，但会增加查询延迟和 CPU 使用量。较低的 EF\$1runtime 可以使查询速度更快、更轻松，但召回率会降低。与 M 或 EF\$1construction 不同，此参数不会影响索引大小或构建时间，因此是在构建索引后在召回率和延迟之间取得平衡的理想调整参数。

两种向量搜索算法（Flat 和 HNSW）都支持可选的 `INITIAL_CAP` 参数。指定此参数时，它会为索引预先分配内存，从而减少内存管理开销并提高向量摄取速度。与 HNSW 相比，扁平索引支持更快的摄取速度。

类似于 HNSW 的向量搜索算法可能无法高效处理对先前插入向量的删除或覆盖。使用这些操作可能会导致索引内存消耗过多，从而 and/or 降低召回质量。重新索引是恢复最佳内存使用 and/or 回调的一种方法。

## 向量搜索安全
<a name="vector-search-security"></a>

[针对命令和数据访问的 Valkey ACL（访问控制列表）](https://valkey.io/topics/acl/)安全机制已扩展到控制搜索工具。系统完全支持针对单个搜索命令进行 ACL 控制。提供了一个新的 ACL 类别 `@search`，并更新了许多现有类别（`@fast`、`@read`、`@write` 等），以包含新命令。搜索命令不会修改键数据，这意味着将保留现有的 ACL 写入访问机制。`HASH` 和 `JSON` 操作的访问规则不因索引的存在而改变；这些命令仍然受到普通键级别访问控制的约束。

带索引的搜索命令也可以通过 ACL 进行访问控制。访问检查在整个索引级别执行，而不是在每个键级别执行。这意味着，只有当用户有权访问该索引键空间前缀列表中所有可能的键时，系统才会向该用户授予对该索引的访问权限。换句话说，索引的实际内容并不能控制访问权限。用于安全检查的是前缀列表定义的索引理论内容。可能出现用户对密钥具有读 and/or 写权限但无法访问包含该密钥的索引的情况。请注意，创建或使用索引只需要具有对键空间的读取访问权限，而不考虑是否有写入访问权限。