数据库管理285期 20245-01-17
- 数据库管理-第285期 Oracle 23ai:深入浅出向量索引(20250117)
- 1 HNSW
- 事务支持
- 解读
- 2 IVF
- 分区支持
- 解读
- 3 混合向量索引
- 何时选择混合向量索引
- 为何选择混合向量索引
- 总结
数据库管理-第285期 Oracle 23ai:深入浅出向量索引(20250117)
作者:胖头鱼的鱼缸(尹海文)
Oracle ACE Pro: Database
PostgreSQL ACE Partner10年数据库行业经验
拥有OCM 11g/12c/19c、MySQL 8.0 OCP、Exadata、CDP等认证
墨天轮MVP,ITPUB认证专家
圈内拥有“总监”称号,非著名社恐(社交恐怖分子)公众号:胖头鱼的鱼缸
CSDN:胖头鱼的鱼缸(尹海文)
墨天轮:胖头鱼的鱼缸
ITPUB:yhw1809。
除授权转载并标明出处外,均为“非法”抄袭
之前写Oracle Vector DB和AI Vector Search相关文章的时候,似乎一直没有针对向量近似相似性搜索的性能优化进行介绍,对于数据库来说,加速数据查询最便捷的方式就是增加索引,那么向量的索引和传统标量数据的索引有什么异同呢,本期和总监一起学习。(本文大部分内容源自于Oracle官方文档)
1 HNSW
HNS,Navigable Small World,可译作可导航小世界,其理念是构建一个邻近图,其中图中的每个向量根据下面3个特征连接到其他几个向量:
- 向量之间的距离
- 插入期间搜索的每个步骤中考虑的最近向量候选的最大数量 (EFCONSTRUCTION)
- 每个向量允许的最大连接数 (NEIGHBORS)
如果上述两个阈值的组合过高,则最终可能会得到一个紧密连接的图,这会减慢搜索过程。另一方面,如果这些阈值的组合过低,则图可能会变得过于稀疏和/或断开连接,这使得在搜索过程中很难找到某些向量之间的路径。
用于向量搜索的可导航小世界 (NSW) 图遍历从图中预定义的入口点开始,访问一组密切相关的向量。搜索算法采用两个关键列表:候选列表(遍历图时遇到的动态更新向量列表)和结果列表(包含迄今为止找到的与查询向量最接近的向量)。随着搜索的进行,算法会浏览整个图,通过探索和评估可能比结果中的向量更近的向量来不断优化候选列表。一旦候选列表中没有比结果中最远的向量更近的向量,则该过程结束,这表明已达到局部最小值并已确定与查询向量最接近的向量。下图对这一点进行了展示:
所述方法在将向量插入到图中的一定规模时表现出稳健的性能。超过此阈值后,分层可导航小世界 (HNSW,Hierarchical Navigable Small World) 方法通过引入多层层次结构来增强 NSW 模型,类似于概率跳跃列表中观察到的结构。此分层架构是通过将图的连接分布在多个层上来实现的,并以每个后续层包含来自下一层链接子集的方式组织它们。这种分层确保顶层捕获长距离链接,有效地充当图中的快速路径,而较低层则专注于较短的链接,从而促进细粒度的本地导航。因此,搜索从较高层开始,以快速近似目标向量的区域,逐渐移动到较低层以进行更精确的搜索,通过利用从顶层移动到底层时向量之间的较短链接(较小距离),显著提高搜索效率和准确性。为了更好地理解 HNSW 的工作原理,让我们看看此层次结构如何用于概率跳过列表结构:
概率跳跃表结构使用多层链接列表,其中上层跳过的数字比下层跳过的数字多。在此示例中,要搜索数字 17。从顶层开始,然后跳转到下一个元素,直到找到 17、到达列表末尾或找到大于 17 的数字。当到达列表末尾或找到大于 17 的数字时,则从上一层中最新的小于 17 的数字开始。
HNSW 使用与 NSW 层相同的原理,即较高层中的向量之间的距离较大。以下 2D 空间中的图表说明了这一点:
最顶层是最长的边,最底层是最短的边。
从顶层开始,一层中的搜索从入口向量开始。然后对于每个节点,如果有一个邻居比当前节点更接近查询向量,则跳转到该邻居。算法一直这样做,直到找到查询向量的局部最小值。当在一层中找到局部最小值时,搜索将使用新层中的相同向量转到下一层,并在该层中继续搜索。此过程重复进行,直到找到底层的局部最小值,其中包含所有向量。此时,搜索转换为使用NSW算法围绕最新找到的局部最小值进行近似相似性搜索,以提取与查询向量最相似的前k个向量。虽然上层可以具有NEIGHBORS参数设置的每个向量的最大连接数,但第0层可以具有两倍的连接数。下图说明了此过程:
层是使用内存图(而非 Oracle 内存图)实现的。每个层都使用单独的内存图。如前所述,在创建HNSW索引时,可以使用 NEIGHBORS 参数微调上层中每个向量的最大连接数,以及使用EFCONSTRUCTION参数微调插入期间搜索的每个步骤中考虑的最近向量候选的最大数量,其中EF代表Enter Factor。
如前所述,在使用Oracle AI Vector Search使用HNSW索引运行近似搜索查询时,可以指定应执行近似搜索的目标精度。
对于HNSW近似搜索,可以指定目标精度百分比值来影响探测搜索时考虑的候选数。这是由算法自动计算的。值为 100 往往会产生与精确搜索类似的结果,尽管系统可能仍会使用索引并且不会执行精确搜索。优化器可能会选择继续使用索引,因为考虑到查询中的谓词,这样做可能会更快。可以指定EFSEARCH参数来规定在探测索引时要考虑的候选的最大数量,而不是指定目标准确度百分比值。该数字越高,准确度越高。
注意:
· 如果未在近似搜索查询中指定任何目标精度,那么将继承创建索引时设置的目标精度。将看到,在创建索引时,可以根据要创建的索引类型使用百分比值或参数值指定目标精度。
· 与索引创建时设置的目标精度相比,在索引搜索时可以指定不同的目标精度。对于HNSW索引,可以使用EFSEARCH参数(高于索引创建时指定的EFCONSTRUCTION值)查看更多邻居以获得更准确的结果。在索引创建期间提供的目标精度决定了索引创建参数,并且还充当向量索引搜索的默认精度值。
事务支持
HNSW索引图是静态的纯内存结构。使用两个主要结构对具有 HNSW 索引的表进行事务维护:私有日志(private journal)和共享日志(shared journal)。
- 私有日志是每个事务的内存数据结构,用于跟踪由事务添加或删除的向量(更新实际上是删除后插入)。这类似于用于维护内存列存储数据的事务日志。这些内存结构来自向量内存池,用于读取一致性目的。
- 共享日志包含提交系统更改号(SCN)和相应的修改行。此结构是在创建向量索引时创建的磁盘结构。在提交时,记录到私有日志中的更改将转换为行并刷新到共享日志中。此结构还用于读取一致性目的。
注意:
· 对于批量DML(使用 INSERT /*+ APPEND */ 直接加载),更改会直接在共享日志中跟踪,以避免对向量内存池造成压力。
· 在完全重新填充时(直到新的HNSW图可用),如果查询尝试访问不再存在的旧版本的HNSW图,则会触发读取一致性错误ORA 51815 "INMEMORY NEIGHBOR GRAPH HNSW vector index snapshot is too old"。
例如,假设旧的HNSW图存在于SCN 100。虽然完全重新填充会在SCN 200处构建新图(这将创建新的ROWID到VID映射表),但到达SCN 150的查询无法访问 SCN 200 处的新图。这是因为查询的执行计划是使用与SCN 100处的旧图相对应的旧ROWID到VID映射表编译的。
除了先前定义的主要用于事务一致性的结构之外,还可以维护完整的检查点磁盘结构(如果启用),以便在实例重启后更快地重新加载HNSW索引。在创建索引并完全重新填充 HNSW 图时,会自动创建完整的检查点。默认情况下,HNSW 检查点处于启用状态。
如何将先前定义的结构相互结合使用,以便在具有HNSW索引的表上实现事务维护和读取一致性的整体更好性能:
- 按照DML,通过考虑内存中现有的HNSW图以及查询的私有日志和共享日志来确定事务一致的已删除和插入向量集列表,从而实现读取一致性。这包括从日志中识别已删除向量的精确列表,通过增强过滤器以忽略已删除向量,对当前版本的HNSW索引运行近似 top-K 搜索,对日志中新插入的向量运行精确top-k搜索,并合并两次搜索的结果。
- 随着DML在共享日志中积累,在磁盘日志中精确搜索已删除和插入的向量会导致其性能下降。为了最大限度地减少这种影响,会自动触发索引的完整重新填充。在后台重新填充HNSW索引的决定基于一个默认阈值,该阈值代表针对索引运行的DML数量的一定百分比。此外,每次创建或重新填充HNSW索引时,都会在磁盘上重新创建新创建的图形的完整检查点和新的ROWID到VID映射表。
注意:
在完全重新填充期间,内存中需要两个图形副本。例如,如果我们有10%的新插入,那么重新填充图形的向量内存需求将比内存中原始HNSW图形大小大约多10%。因此,在重新填充期间的峰值向量内存需求下,内存需求将是2.1倍,而在重新填充完成后,内存需求将降至1.1倍。这样做是为了确保在创建新图形时仍可以使用先前版本的图形实现读取一致性。
解读
从HNSW索引的概念来看,要支持DML的难度和开销还是很大的。因此在很多数据库(前提是支持向量DML操作)中,在存储有向量数据的表上建立HNSW索引后,是不允许再进行DML操作的,DML操作也需要删除后重建HNSW索引。而在Oracle 23.4和23.5中,对于在向量列上构建了HNSW索引的表,也是不允许使用DML。HNSW支持DML操作功能是在23.6实现的。
2 IVF
IVF,Inverted File Flat,可译作倒排文件平面,IVF向量索引是一种通过使用邻居分区或集群来缩小搜索区域以提高搜索效率的技术。下图描述了使用二维空间表示进行近似搜索时如何创建分区或聚类。但这可以推广到更高维的空间。
×表示此空间中的向量数据点。
添加新数据点(显示为小圆圈)以识别k个分区质心,其中质心的数量(k)由数据集的大小(n)决定。通常,k设置为 n 的平方根,但可以在创建索引期间通过指定NEIGHBOR PARTITIONS参数进行调整。
每个质心代表相应分区的平均向量(重心)。
质心是通过对向量进行训练计算得出的,其目标是最小化每个向量与最近质心的总距离。
质心最终将向量空间划分为k个分区。这种划分在概念上表现为从质心扩展的圆圈,当它们相遇时停止增长,形成不同的分区。
除了外围的向量之外,每个向量都落在与质心相关的特定分区内。
对于查询向量vq,搜索算法会识别最近的i个质心,其中i默认为k的平方根,但可以通过设置NEIGHBOR PARTITION PROBES参数针对特定查询进行调整。此调整允许在搜索速度和准确性之间进行权衡。
此参数的数字越大,准确性越高。在此示例中,i设置为2,两个已识别的分区是分区编号1和3。
一旦确定了i个分区,就会对它们进行全面扫描,以识别出本例中前5个最近的向量。这个数字5可以与k不同,可以在查询中指定这个数字。下图突出显示了在分区编号1和3中找到的离vq最近的五个向量。
此方法构成近似搜索,因为它将搜索限制在分区的子集内,从而加速了搜索过程,但可能会在未检查的分区中丢失更接近的向量。此示例说明近似搜索可能无法产生离vq最近的准确向量,这表明搜索效率和准确性之间存在固有的权衡。
但是,距离vq最近的5个向量并不是通过近似搜索找到的向量。可以看到分区号4中的一个向量比分区号3中检索到的向量之一更接近vq。
现在可以看到为什么使用向量索引搜索并不总是精确搜索,而是近似搜索。在此示例中,近似搜索准确率仅为 80%,因为它仅检索了5个精确搜索向量结果中的4个。
使用Oracle AI Vector Search运行使用向量索引的近似搜索查询时,可以指定近似搜索应执行的目标精度。
对于IVF近似搜索,可以指定目标精度百分比值来影响用于探测搜索的分区数。该值由算法自动计算。值为100时,系统可能会强制执行精确搜索,但系统仍可能使用索引,不会执行精确搜索。优化器可能会选择继续使用索引,因为考虑到查询中的谓词,这样做可能会更快。可以指定NEIGHBOR PARTITION PROBES参数来强制搜索要探测的分区的最大数量,而不是指定目标精度百分比值。该数字越高,精度越高。
注意:
· 如果未在近似搜索查询中指定任何目标精度,那么将继承创建索引时设置的目标精度。将看到,在创建索引时,可以根据要创建的索引类型使用百分比值或参数值指定目标精度。
· 与索引创建时设置的目标精度相比,可以在索引搜索时指定不同的目标精度。对于 IVF 索引,可以使用NEIGHBOR PARTITION PROBES参数探测更多质心分区以获得更准确的结果。在索引创建期间提供的目标精度决定了索引创建参数,并且还充当向量索引搜索的默认精度值。
分区支持
IVF向量索引支持分区表上的全局和本地索引。默认情况下,IVF索引按质心全局分区。
全局IVF索引由两个表组成:
- 一个名为VECTOR$<base table name>_IVF_IDX$<object info>$IVF_FLAT_CENTROIDS,包含已识别质心向量和相关ID的列表。
- 第二个名为VECTOR$<base table name>_IVF_IDX$<object info>$IVF_FLAT_CENTROID_PARTITIONS,它按质心 ID 进行列表分区。每个分区包含与该分区的相应质心ID紧密相关(集群)的基表向量。
此结构用于加速索引中的搜索,方法是首先识别最接近查询向量的质心,然后使用相应的质心ID修剪不必要的分区。
但是,如果基表按某些关系数据进行分区,并且查询按基表分区键进行过滤,则全局 IVF 索引不是最佳选择,因为它们完全独立于基表分区键。例如,如果搜索类似于向量化图片的加利福尼亚州前 10 栋房屋,则图片本身很可能与加利福尼亚州没有任何关系。虽然查询受益于基表按州分区的事实,因此只能搜索与加利福尼亚州相对应的分区,但查询仍然必须查看可能不在加利福尼亚州的图片。
为了进一步加速此类查询,可以创建本地IVF索引。索引的术语“本地”是指基表分区或子分区与索引分区之间的一对一关系。
如下图所示,基表有三个分区,创建的本地IVF索引仍然由两个内部表组成:
- 一个名为VECTOR$<base table name>_IVF_IDX$<object info>$IVF_FLAT_CENTROIDS,它按基表分区 ID 进行列表分区,因此与基表等分区。每个分区包含相应标识的质心向量和相关 ID 的列表。
- 第二个名为VECTOR$<base table name>_IVF_IDX$<object info>$IVF_FLAT_CENTROID_PARTITIONS,它按基表分区ID进行列表分区,并按质心ID进行列表子分区。此表也与基表等分区,每个子分区包含与该子分区的相应质心ID紧密相关(集群)的基表向量。
回到我们最初的例子,搜索加利福尼亚州前10栋房屋,类似于向量化图片;查询受益于对基表和质心表(加利福尼亚州)的分区修剪,因为它们都是按州分区的。此外,一旦在该分区中确定了最近的质心,查询只需扫描质心分区表中相应的质心群集子分区,而无需扫描其他质心子分区。
另一种可能性是基表进行复合分区。以下是与该情况相对应的图形表示。质心表根据基表子分区进行列表分区。质心表中的每个分区包含在相应基表子分区中找到的所有质心向量。质心分区表按基表子分区 ID 进行列表分区,并进一步按质心ID进行子分区:
注意:
只能在分区基表上创建本地IVF索引。
本地IVF索引继承常规本地索引使用的所有系统目录表和视图。vecsys.vector$index表中的标志 (idx_spare2)指示索引是本地还是全局向量索引。
使用本地 IVF 索引可带来其他优势:
- 简化分区管理操作 (PMOP,Partition Management Operations):
例如,删除表分区只需删除相应的索引分区。 - 灵活的索引方案:
例如,将某些索引分区标记为UNUSABLE,以避免通过部分索引对某些表分区进行索引。
解读
IVF索引性能低于HNSW索引,但其可以更便携的管理并更好的支持DML操作。
3 混合向量索引
混合向量索引(Hybrid Vector Index)继承了Oracle Text搜索索引的所有信息检索功能,并利用了Oracle AI Vector Search向量索引的语义搜索功能。
混合向量索引允许使用全文搜索和语义向量搜索的组合来索引和查询文档。混合向量索引是一类专门的域索引,它将现有的Oracle Text索引数据结构和向量索引数据结构组合成一个统一的结构。单个索引包含文档的文本和向量字段,使能够同时执行关键字搜索和向量搜索的组合。
混合向量索引的目的是通过允许用户使用开箱即用和自定义评分技术以各种组合方式搜索向量和关键字来增强Oracle Text索引的搜索相关性。通过将传统的基于关键字的文本搜索与基于向量的相似性搜索相结合,可以改善整体搜索体验并为用户提供更准确的信息。
何时选择混合向量索引
如果查询需要语义相似但涉及特定焦点领域(即涉及特定组织、用户名、产品代码、技术术语、日期或时间)的信息,请考虑在混合搜索场景中使用混合向量索引。例如,典型的混合搜索查询可以是查找“ABC 公司股票欺诈的十大实例”。
这样的查询涉及两个独立的部分:
- 第一个是想要识别“股票欺诈”概念的地方
- 第二个是想要缩小结果范围以仅关注“ABC 公司”的地方
纯关键字搜索可能会返回专门包含查询词(如“股票”、“欺诈”、“ABC”或“公司”)的结果,因为它侧重于将精确的关键字或单词或短语的表面表示与文本索引中的标记术语进行匹配。因此,单独的关键字搜索可能不适合这里,因为它可能会忽略我们查询中的单词背后的语义含义,尤其是当内容中没有精确的术语时。
纯向量搜索侧重于理解单词或短语的含义和上下文,而不仅仅是匹配关键字。向量搜索考虑查询词之间的语义关系,因此它可能包含更多与上下文相关的结果,如“公司欺诈”、“股市操纵”、“股票不当行为”、“金融违规行为”或“金融部门的诉讼”。向量搜索也可能不适合这里,因为它可能包含有关涉及 ABC 或类似组织的股票欺诈这一更广泛主题的结果,尤其是当内容中没有精确的短语“ABC 公司股票欺诈”时。
混合搜索可以解决此类查询的两个组成部分,方法是对同一数据运行关键字搜索和向量搜索,然后将两个搜索结果合并为一个结果集。这样,可以利用文本索引和向量索引的优势来检索最相关的结果。
为何选择混合向量索引
混合向量索引的优点:
- 与纯向量搜索或关键字搜索相比,召回率更高:
如前所述,混合搜索可以结合Oracle AI Vector Search和Oracle Text搜索的强大功能,提供更准确和个性化的信息。关键字搜索或向量搜索本身可能与复杂的搜索场景无关,并且可能导致大量虚假结果。 - 减轻分段的缺点:
向量嵌入模型通常会对输入文本的大小施加限制,这会迫使将大型文档拆分为较小的数据块以进行语义搜索(如了解数据转换阶段中所述)。由于截断,数据块可能会丢失原始文档的更广泛上下文,这可能会导致结果丢失。混合向量索引通过在文档级别执行文本搜索来帮助恢复每个文档的整个上下文。 - 与维护独立索引相比,部署和管理更简单:
混合向量索引是一个可以使用DML维护文本和向量的单域索引。关键字搜索和向量搜索都会对所有文档执行,然后将两个搜索结果合并并评分以返回统一的结果集。它提供了端到端索引管道,可自动转换输入数据以进行向量搜索和关键字搜索,从而提高索引性能。此索引公开了可选首选项以配置索引参数,但这不是必需的。 - 统一查询 API,按向量和关键字进行搜索:
单个SEARCH API(可通过DBMS_HYBRID_VECTOR PL/SQL包获得)允许在文档文本索引上指定传统的CONTAINS查询,并在向量化块索引上指定VECTOR_DISTANCE查询。可以在仅关键字、仅向量和混合搜索模式之间切换,以检索最佳文档或块。
总结
本期对Oracle 23ai的向量索引进行了较为深入的介绍。
老规矩,知道写了些啥。