向量搜索概述 - Amazon MemoryDB

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

向量搜索概述

向量搜索在索引创建、维护和使用的基础上建立。每个向量搜索操作都指定一个单一索引,其操作被限定于该索引,也就是说,对一个索引的操作不受任何其他索引操作的影响。除了创建和销毁索引的操作之外,可以随时对任何索引执行任意数量的操作,这意味着在集群级别,可以同时对多个索引执行多个操作。

单个索引是存在于唯一命名空间中的命名对象,该命名空间与其他 Valkey 和 Redis OSS 命名空间分开:键、函数等。从概念上讲,每个索引都类似于传统的数据库表,它的结构有两个维度:列和行。表中的每一行都对应一个键。索引中的每一列对应该键的一个成员或部分。在本文档中,术语“键”、“行”和“记录”的含义相同,可以互换使用。同样,术语“列”、“字段”、“路径”和“成员”的含义在本质上是相同的,可以互换使用。

没有用于添加、删除或修改索引数据的特殊命令。然而,使用现有的 HASHJSON 命令对索引中的键进行修改也会自动更新索引。

索引以及 Valkey 和 Redis OSS 密钥空间

索引是在 Valkey 和 Redis 密钥空间的子集上构建和维护的OSS。多个索引可以不受限制地选择不相交或重叠的密钥空间子集。每个索引的键空间由创建索引时提供的键前缀列表定义。前缀列表是可选的,如果省略,则整个密钥空间将成为该索引的一部分。索引还具有类型,并且仅涵盖具有匹配类型的键。当前,仅支持JSON和HASH索引。索引仅索引其前缀列表所涵盖的HASH键,同样,索引仅索引其前缀列表所涵盖的JSON键。HASH JSON在索引的键空间前缀列表中,未指定类型的键将被忽略,并且也不会影响搜索操作。

当HASH或JSON命令修改位于索引键空间内的键时,该索引就会更新。此过程包括提取每个索引的已声明字段,并使用新值更新索引。更新过程在后台线程中完成,这意味着索引可能需要过一段时间后,才能最终与其键空间内容保持一致。因此,插入或更新键后,可能短时间内不会出现在搜索结果中。在系统负载繁重和/或数据大量变动期间,在搜索结果中看到变化的延迟可能会更长。

索引的创建是一个多步骤过程。第一步是执行英国《金融时报》。 CREATE定义索引的命令。成功执行创建命令后会自动启动第二步:回填。回填过程在后台线程中运行,并在密钥空间中扫描新索引的前缀列表中的密钥。找到的每个键都会添加到索引中。最终,整个键空间都会接受扫描,完成索引创建过程。请注意,在回填过程运行时,允许对索引键进行变更并且没有任何限制,索引回填过程只有在所有键都正确编制索引后才会完成。在索引回填时,不允许尝试查询操作,否则回填终止并显示错误。可以通过执行 FT.INFO 查看索引的输出(“backfill_status”)来确定回填过程的完成情况。

索引字段类型

索引的每个字段(列)都有创建索引时声明的特定类型,并且有一个键内位置。对于HASH密钥,位置是其中的字段名称HASH。对于JSON密钥,位置是JSON路径描述。修改键时,系统会提取与已声明字段关联的数据,将其转换为声明的类型并存储在索引中。如果数据丢失或无法成功转换为声明的类型,则该字段将从索引中省略。有四种类型的字段,如下所述:

  • 数值字段包含一个数字。对于JSON字段,必须遵循JSON数字的数值规则。对于HASH,该字段应包含以固定点数或浮点数的标准格式书写的数字的ASCII文本。无论键内的表示形式如何,字段都将转换为在索引中存储的 64 位浮点数。数值字段可以与范围搜索运算符搭配使用。基础数字以浮点数形式存储并且有精度限制,因此适用于浮点数比较的常用规则对于数值字段也适用。

  • 标签字段包含零个或多个编码为单个 UTF -8 字符串的标签值。字符串解析为使用分隔符(默认为英文逗号,但可更改)分隔的标签值,并删除前导和尾随空格。单个标签字段中可以包含任意数量的标签值。对于标签字段,可以在查询时对标签值进行筛选,并且可以选择区分大小写或不区分大小写。

  • 文本字段包含不必兼容 UTF -8 的字节。对于文本字段,可使用与应用程序相关的值对查询结果进行修饰。例如 a URL 或文档的内容等。

  • 向量字段包含一个数字向量,也称为嵌入。向量字段支持使用指定的算法和距离度量对固定大小的向量进行 K 最近邻搜索 (KNN)。对于HASH索引,该字段应包含以二进制格式(little-IEEE endian 754)编码的整个向量。对于JSON键,路径应引用一个填充数字的正确大小的数组。请注意,当使用JSON数组作为向量场时,JSON键内数组的内部表示形式会转换为所选算法所需的格式,从而减少内存消耗和精度。使用这些JSON命令的后续读取操作将产生降低的精度值。

向量索引算法

系统提供两种向量索引算法:

  • Flat – Flat 算法是对索引中每个向量进行暴力线性处理,提供距离计算精度范围内的精确答案。由于索引采用线性处理,因此对于大型索引,此算法的运行时间可能非常长。

  • HNSW(分层导航小世界)— 该HNSW算法是一种替代方案,它提供了正确答案的近似值,以换取大幅缩短的执行时间。该算法由 MEF_CONSTRUCTIONEF_RUNTIME 三个参数控制。前两个参数在创建索引时指定,无法更改。EF_RUNTIME 参数的默认值在创建索引时指定,但之后可以在任何单独的查询操作中更改。这三个参数相互作用,以平衡摄取和查询操作期间的内存和CPU消耗,并控制精确KNN搜索近似值的质量(称为召回率)。

两种向量搜索算法(Flat 和HNSW)都支持可选INITIAL_CAP参数。指定此参数时,它会为索引预先分配内存,从而减少内存管理开销并提高向量摄取速度。

像这样的矢量搜索算法HNSW可能无法有效地处理先前插入的向量的删除或覆盖。使用这些操作可能会导致and/or degraded recall quality. Reindexing is one method for restoring optimal memory usage and/or召回过多的索引内存消耗。

向量搜索查询表达式

英国《金融时报》 SEARCH和《金融时报》。 AGGREGATE命令需要查询表达式。该表达式是一个单字符串参数,由一个或多个运算符组成。每个运算符使用索引中的一个字段来标识索引中键的子集。可以使用布尔组合器和括号将多个运算符组合起来,以进一步增强或限制收集的键集合(或结果集)。

通配符

通配符运算符,即星号(“*”),可匹配索引中的所有键。

数值范围

数值范围运算符使用以下语法:

<range-search> ::= '@' <numeric-field-name> ':' '[' <bound> <bound> ']' <bound> ::= <number> | '(' <number> <number> ::= <integer> | <fixed-point> | <floating-point> | 'Inf' | '-Inf' | '+Inf'

< numeric-field-name > 必须是声明的类型字段NUMERIC。默认情况下包含边界值,但可以使用前导左圆括号 [“(”] 来排除边界值。通过使用 Inf+Inf-Inf 作为边界之一,可以将范围搜索转换为单个关系比较(<、<=、>、>=)。无论指定哪种数值格式(整数、固定点、浮点、无穷大),数字都会转换为 64 位浮点数进行比较,并相应地降低精度。

例 示例
@numeric-field:[0 10] // 0 <= <value> <= 10 @numeric-field:[(0 10] // 0 < <value> <= 10 @numeric-field:[0 (10] // 0 <= <value> < 10 @numeric-field:[(0 (10] // 0 < <value> < 10 @numeric-field:[1.5 (Inf] // 1.5 <= value

标签比较

标签比较运算符使用以下语法:

<tag-search> ::= '@' <tag-field-name> ':' '{' <tag> [ '|' <tag> ]* '}'

如果运算符中的任何标签与记录的标签字段中的任何标签匹配,则该记录将包含在结果集中。采用 <tag-field-name> 设计的字段必须是用 TAG 类型声明的索引字段。标签比较的示例包括:

@tag-field:{ atag } @tag-field: { tag1 | tag2 }

布尔值组合

可以使用布尔逻辑组合数字运算符或标签运算符的结果集:and/or. Parentheses can be used to group operators and/or更改计算顺序。布尔逻辑运算符的语法为:

<expression> ::= <phrase> | <phrase> '|' <expression> | '(' <expression> ')' <phrase> ::= <term> | <term> <phrase> <term> ::= <range-search> | <tag-search> | '*'

将多个术语组合成短语时使用“and”运算。使用竖线(“|”)组合多个短语时使用“or”运算。

向量索引支持两种不同的搜索方法:最近邻和范围。最近邻搜索会在索引中找到最接近所提供的(参考)向量的数字 K,通俗地称KNN之为 “K” 最近邻域。KNN搜索的语法是:

<vector-knn-search> ::= <expression> '=>[KNN' <k> '@' <vector-field-name> '$' <parameter-name> <modifiers> ']' <modifiers> ::= [ 'EF_RUNTIME' <integer> ] [ 'AS' <distance-field-name>]

向量KNN搜索仅适用于满足的向量,<expression>这些向量可以是上面定义的运算符的任意组合:通配符、范围搜索、标签搜索和/或它们的布尔组合。

  • <k> 是一个整数,指定要返回的近邻向量的数量。

  • <vector-field-name> 必须指定类型为 VECTOR 的已声明字段。

  • <parameter-name> 字段指定 FT.SEARCHFT.AGGREGATE 命令 PARAM 表中的一个条目。此参数是距离计算的参考向量值。向量的值以 little-endian IEEE 754 二进制格式编码为该PARAM值(与向量场的编码方式相同)HASH

  • 对于类型的向量索引HNSW,可选EF_RUNTIME子句可用于覆盖创建索引时建立的EF_RUNTIME参数的默认值。

  • 可选的 <distance-field-name> 为结果集提供了一个字段名称,用于包含参考向量和定位键之间的计算距离。

范围搜索可找到距离参考向量指定距离(半径)内的所有向量。范围搜索的语法是:

<vector-range-search> ::= ‘@’ <vector-field-name> ‘:’ ‘[’ ‘VECTOR_RANGE’ ( <radius> | ‘$’ <radius-parameter> ) $<reference-vector-parameter> ‘]’ [ ‘=’ ‘>’ ‘{’ <modifiers> ‘}’ ] <modifiers> ::= <modifier> | <modifiers>, <modifier> <modifer> ::= [ ‘$yield_distance_as’ ‘:’ <distance-field-name> ] [ ‘$epsilon’ ‘:’ <epsilon-value> ]

其中:

  • <vector-field-name>是要搜索的向量字段的名称。

  • <radius> or $<radius-parameter>是搜索距离的数字限制。

  • $<reference-vector-parameter> 是包含参考向量的参数的名称。向量的值以 little-endian IEEE 754 二进制格式编码为该PARAM值(与向量场的编码相同)HASH

  • 可选项为结果集<distance-field-name>提供了一个字段名称,用于包含参考向量和每个键之间的计算距离。

  • 可选<epsilon-value> 控制搜索操作的边界,遍历距离<radius> * (1.0 + <epsilon-value>) 内的向量以寻找候选结果。默认值为 .01。

INFO命令

向量搜索功能增强了 Valkey 和 Redis OSS INFO命令,增加了几个统计数据和计数器部分。请求检索 SEARCH 部分将检索以下所有部分:

search_memory 部分

名称 描述
search_used_memory_bytes 所有搜索数据结构消耗的内存字节数
search_used_memory_human 上述内存消耗的人类可读版本

search_index_stats 部分

名称 描述
search_number_of_indexes 已创建的索引数量
search_num_fulltext_indexes 所有索引中非向量字段的数量
search_num_vector_indexes 所有索引中向量字段的数量
search_num_hash_indexes HASH类型键上的索引数量
search_num_json_indexes JSON类型键上的索引数量
search_total_indexed_keys 所有索引键总数
search_total_indexed_vectors 所有索引中的向量总数
search_total_indexed_hash_keys 所有索引HASH中该类型的键总数
search_total_indexed_json_keys 所有索引中类型为 type JSON 的键总数
search_total_index_size 所有索引使用的字节数
search_total_fulltext_index_size 非向量索引结构使用的字节数
search_total_vector_index_size 向量索引结构使用的字节数
search_max_index_lag_ms 上次摄取批量更新期间的摄取延迟

search_ingestion 部分

名称 描述
search_background_indexing_status 摄取状态。NO_ACTIVITY 表示闲置。其他值表示有键正在进行摄取。
search_ingestion_paused 除了在重新启动期间,此值始终应为“no”。

search_backfill 部分

注意

本部分中记录的某些字段只有在当前存在回填操作时才可见。

名称 描述
search_num_active_backfills 当前回填活动数量
search_backfills_paused 除非内存不足,否则此值始终应为“no”。
搜索当前回填进度百分比 当前回填的完成百分比 (0-100)

search_query 部分

名称 描述
search_num_active_queries 当前正在执行的 FT.SEARCHFT.AGGREGATE 命令的数量

向量搜索安全

ACL(访问控制列表)命令和数据访问的安全机制已扩展到控制搜索工具。ACL完全支持控制单个搜索命令。提供了一个新ACL类别@search,,并更新了许多现有类别(@fast@read@write、、等)以包含新命令。搜索命令不会修改密钥数据,这意味着现有的写入权限ACL机制得以保留。索引的存在不会修改HASH和JSON操作的访问规则;普通的密钥级访问控制仍然适用于这些命令。

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

有关与 MemoryDB ACLs 配合使用的更多信息,请参阅使用访问控制列表对用户进行身份验证 ()。ACLs