Elasticsearch 中的矢量搜索:设计背后的基本原理

作者:Adrien Grand

你是否有兴趣了解 Elasticsearch 用于矢量搜索(vector search)的特性以及设计是什么样子? 一如既往,设计决策有利有弊。 本博客旨在详细介绍我们如何选择在 Elasticsearch 中构建矢量搜索。

矢量搜索通过 Apache Lucene 集成到 Elasticsearch 中

首先是有关 Lucene 的一些背景知识:Lucene 将数据组织成定期合并的不可变段(segments)。 添加更多文档需要添加更多段。 修改现有文档需要自动添加更多段并将这些文档的先前版本标记为已删除。 段内的每个文档都由文档 ID 标识,文档 ID 是该文档在段内的索引,类似于数组的索引。 这种方法的动机是管理倒排索引,倒排索引不擅长就地修改,但可以有效地合并。

除了倒排索引之外,Lucene 还支持存储字段(stored fields,一个文档存储)、文档值(doc values,列式存储)、术语向量(term vectors, 每个文档的倒排索引)及其段中的多维点。 矢量已以相同的方式积分:

  • 新矢量在索引时缓冲到内存中。
  • 当超过索引时间缓冲区的大小或必须使更改可见时,这些内存中的缓冲区将被序列化为段的一部分。
  • 段(segements)会在后台定期合并在一起,以控​​制段总数并限制每个段的总体搜索时间开销。 由于它们是段的一部分,因此矢量也需要合并。
  • 搜索必须组合索引中所有段的顶部矢量命中。
  • 对矢量的搜索必须查看实时文档集,以便排除标记为已删除的文档。

上面的系统是由 Lucene 的工作方式驱动的。

Lucene 目前使用分层可导航小世界 (Hierarchical Navigable Small World - HNSW) 算法来索引矢量。 在较高层次上,HNSW 将矢量组织成一个图表,其中相似的矢量可能会连接起来。 HNSW 是矢量搜索的热门选择,因为它相当简单,在矢量搜索算法的比较基准上表现良好,并且支持增量插入。 Lucene 对 HNSW 的实现遵循 Lucene 将数据保留在磁盘上并依靠页面缓存来加速对频繁访问的数据的访问的准则。

近似向量搜索通过 knn 部分在 Elasticsearch 的 _search API 中公开。 使用此功能将直接利用 Lucene 的矢量搜索功能。 矢量还集成在 Elasticsearch 的脚本 API 中,允许执行精确的强力搜索(brute-force search),或利用矢量进行重新评分。

现在让我们深入探讨通过 Apache Lucene 集成矢量搜索的优缺点。

缺点

利用 Apache Lucene 进行矢量搜索的主要缺点是 Lucene 将矢量与段联系起来。 然而,正如我们稍后将在 优点 ”部分中看到的,将矢量与段联系起来也是实现高效预过滤、高效混合搜索和可见性一致性等主要功能的原因。

合并需要重新计算 HNSW 图

段合并需要采用 N 个输入段(默认合并策略通常为 10 个),并将它们合并为单个段。Lucene 当前从没有删除操作的最大输入段创建 HNSW 图的副本,然后将来自其他段的矢量添加到此 HNSW 图。 与在索引的生命周期内就地改变单个 HNSW 图相比,这种方法会产生索引时间开销,因为段是合并的。

搜索需要合并多个细分的结果

由于索引由多个段组成,因此搜索需要计算每个段上的 top-k 矢量,然后将这些每个段的 top-k 命中合并为全局 top-k 命中。 通过并行搜索段可以减轻对延迟的影响,但与搜索单个 HNSW 图相比,这种方法仍然会产生一些开销。

RAM 需要随着数据集的大小进行扩展以保持最佳性能

遍历 HNSW 图会产生大量随机访问。 为了高效执行,数据集应适合页面缓存,这需要根据所管理的矢量数据集的大小调整 RAM 的大小。 除了 HNSW 之外,还存在其他用于矢量搜索的算法,它们具有更适合磁盘的访问模式,但它们也有其他缺点,例如更高的查询延迟或更差的召回率。

优点

数据集可以扩展到超出 RAM 总大小

由于数据存储在磁盘上,Elasticsearch 将允许数据集大于本地主机上可用的 RAM 总量,并且随着页面缓存中可容纳的 HNSW 数据比例的降低,性能将会下降。 如上一节所述,注重性能的用户需要根据数据集的大小来调整 RAM 大小,以保持最佳性能。

无锁搜索

就地更新数据结构的系统通常需要加锁,以保证并发索引和搜索下的线程安全。 Lucene 基于段的索引从不需要在搜索时锁定,即使在并发索引的情况下也是如此。 相反,索引所组成的段集会定期以原子方式更新。

支持增量更改

可以随时添加、删除或更新新矢量。 其他一些近似最近邻搜索(approximate nearest neighbor search)算法需要提供整个矢量数据集。 然后,一旦提供了所有矢量,就执行索引训练步骤。 对于这些其他算法,对矢量数据集的任何重大更新都需要再次完成训练步骤,这可能会导致计算成本高昂。

与其他数据结构的可见性一致性

在如此低的级别集成到 Lucene 的一个好处是,在查看索引的时间点视图时,我们可以与其他开箱即用的数据结构保持一致。 如果你执行文档更新以更新其矢量和某些其他关键字字段,则并发搜索保证会看到矢量字段的旧值和关键字字段的旧值 -- 如果时间点视图是在更新之前创建的,或者是矢量场的新值和关键字字段的新值(如果时间点视图是在更新之后创建的)。 与删除类似,如果文档被标记为已删除,那么包括矢量存储在内的所有数据结构都将忽略它,或者如果它们对删除之前创建的时间点视图进行操作,则它们将看到它。

增量快照

矢量是段的一部分,这一事实有助于快照通过利用两个后续快照通常共享其大部分段(尤其是较大的段)的事实来保持增量。 使用就地修改的单个 HNSW 图不可能实现增量快照(incremental snapshot)。

过滤和混合支持

直接集成到 Lucene 中还可以与其他 Lucene 功能高效集成,例如使用任意 Lucene 过滤器预过滤矢量搜索或将来自矢量查询的命中与来自传统全文查询的命中组合起来。

通过拥有自己的与段关联的 HNSW 图,并且其中节点由文档 ID 索引,Lucene 可以就如何最好地预过滤矢量搜索做出有趣的决定:要么通过线性扫描与过滤器匹配的文档(如果有选择性),或者通过遍历图并仅考虑与过滤器匹配的节点作为 top-k 矢量的候选节点。

与其他功能的兼容性

由于矢量存储与任何其他 Lucene 数据结构一样,因此许多功能与矢量和矢量搜索自动兼容,包括:

  • 聚合
  • 文档级安全性
  • 字段级安全
  • 索引排序

通过脚本访问向量(例如,从 script_score 查询或重新排序)

展望未来:索引和搜索分离

正如另一篇博客中所讨论的,Elasticsearch 的未来版本将在不同的实例上运行索引和搜索工作负载。 该实现本质上看起来就像你不断在索引节点上创建快照并在搜索节点上恢复它们​​。 这将有助于防止矢量索引的高成本影响搜索。 使用单个共享 HNSW 图而不是多个段来实现索引和搜索的这种分离是不可能的,除非每次需要在新搜索中反映更改时通过网络发送完整的 HNSW 图。

结论

总的来说,Elasticsearch 提供了出色的向量搜索功能,并与其他 Elasticsearch 功能集成:

  • 矢量搜索可以通过任何支持的过滤器进行预过滤,包括最复杂的过滤器。
  • 矢量命中可以与任意查询的命中相结合。
  • 矢量搜索与聚合、文档级安全性、字段级安全性、索引排序等兼容。
  • 包含向量的索引仍然遵循与其他索引相同的语义,包括 _refresh、_flush 和 _snapshot API。 它们还将支持无状态 Elasticsearch 中索引和搜索的分离。

这是以一些索引时间和搜索时间开销为代价完成的。 也就是说,矢量搜索通常仍然以数十或数百毫秒的数量级运行,并且比强力(brute force)精确搜索快得多。 更一般地说,与现有比较基准*中的其他向量存储相比,索引时间和搜索时间开销似乎都是可控的(查找 “luceneknn” 行)。 我们还相信,通过将矢量搜索与其他功能相结合,可以释放矢量搜索的许多价值。 此外,我们建议你查看 KNN 搜索调整指南,其中列出了许多有助于减轻上述缺点的负面影响的措施。

我希望你喜欢这个博客。 如果你有疑问,请随时通过讨论与我们联系。你可以随意在现有部署中尝试矢量搜索,或者在 Elastic Cloud 上免费试用 Elasticsearch Service(始终具有最新版本的 Elasticsearch)。

*在撰写本文时,这些基准测试尚未利用矢量化。 有关矢量化的更多信息,请阅读此博客。

本文中描述的任何特性或功能的发布和时间安排均由 Elastic 自行决定。 当前不可用的任何特性或功能可能无法按时交付或根本无法交付。

原文:Vector search in Elasticsearch: The rationale behind the design | Elastic Blog

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/1382.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

python和django中安装mysqlclient失败的解决方案

在Pychram中和pip中安装mysqlclient都不成功,只能直接下载二进制包进行安装了,下载页面中根据python的版本选择对应WHL包下载,下载地址 mysqlclient PyPIhttps://pypi.org/project/mysqlclient/#files 通过pip命令进行安装 pip install d:\…

考研线性代数考点总结

一.行列式 1.数字型行列式 数字行列式的计算含零子式的分块计算 2.行列式的性质 |A||A^T|交换行列,行列式的值变号含公因子的提出或乘进去把某行的K倍加到另一行,行列式的值不变。行列式可以根据某一行或某一列分拆 3.抽象行列式 n阶或高阶行列式 常…

《微服务架构设计模式》第十三章 微服务架构的重构策略

微服务架构的重构策略 一、重构到微服务需要考虑的问题1、为什么重构2、重构形式3、重构策略 二、设计服务与单体的协作方式三、总结 一、重构到微服务需要考虑的问题 1、为什么重构 单体地狱造成的业务问题: 交付缓慢充满故障的软件交付可扩展性差 2、重构形式 …

Visual Studio 向工程中添加现有文件夹

前言: 在创建C#类库(dll)工程后,需要把现有的C#文件添加进工程中 步骤1.将所有文件夹复制到工程中 步骤2. 点击这个图标,显示所有文件夹 工程目录下的所有文件夹都会被显示出来 选中需要添加的文件夹,右…

Linux安装MongoDB数据库,并内网穿透远程连接

文章目录 前言1. 配置Mongodb源2. 安装MongoDB3. 局域网连接测试4. 安装cpolar内网穿透5. 配置公网访问地址6. 公网远程连接7. 固定连接公网地址8. 使用固定地址连接 前言 MongoDB是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富&…

虚拟化容器化与docker

虚拟化容器化与docker 基本概念虚拟化分类虚拟化实现主机虚拟化实现容器虚拟化实现命名空间namespace空间隔离 控制组群cgroup资源隔离 LXC(Linux Container) docker与虚拟机 基本概念 物理机: 实际的服务器或者计算机。相对于虚拟机而言的对实体计算机的称呼。物理…

初识Redis——Redis概述、安装、基本操作

目录 一、NoSQL介绍 1.1什么是NoSQL 1.2为什么会出现NoSQL技术 1.3NoSQL的类别 1.4传统的ACID是什么 1.5 CAP 1.5.1 经典CAP图 1.5.4 什么是BASE 二、Redis概述 2.1 什么是Redis 2.2 Redis能干什么 2.3 Redis的特点 2.4 Redis与memcached对比 2.5 Redis的安装 2.6 Docker安装 三…

二、学习回归 - 基于广告费预测点击量

山外风雨三尺剑 有事提剑下山去 云中花鸟一屋书 无忧翻书圣贤来 1.设置问题 以Web广告和点击量的关系为例来学习回归。 前提:投入的广告费越多,广告的点击量就越高。 根据以往的经验数据,可以得到下图: 那么假设我要投200块的广…

SeLa:Self Labeling Via Simultaneous Clustering and Representation Learning

方法论 有监督的分类任务实现 给定一个将数据I映射至特征向量 x ∈ R D x ∈ R^D x∈RD 的深度神经网络 Φ Φ Φ ,即 x Φ ( I ) x Φ ( I ) xΦ(I)。使用有N个样本 I 1 , … , I N I_1 , … , I_N I1​,…,IN​, 且具有标签 y 1 , … , y N ∈ { 1 , … , K }…

Office如何通过VSTO进行WORD插件开发?

文章目录 0.引言1.工具准备2.WORD外接程序创建和生成3.外接程序生成并使用 0.引言 VSTO(Visual Studio Tools for Office )是VBA的替代,是一套用于创建自定义Office应用程序的Visual Studio工具包。VSTO可以用Visual Basic 或者Visual C#扩展…

华为ospf路由协议在局域网中的高级应用案例

关键配置: 1、出口为ospf区域0,下联汇聚依次区域1、2…,非骨干全部为完全nssa区域 2、核心(abr)上对非骨干区域进行路由汇总,用于解决出口两台路由的条目数量 3、ospf静默接口配置在汇聚下联接接入交换机的…

在Microsoft Excel中如何快速将上下两行数据合并为一行?

合并单元格是电子表格初学者最常用的选项之一。当一组单元格、行或列需要标题或标签时,合并单元格是一种常用的技术。 合并单元格时,仅保留区域左上角单元格中的值或公式,并将其显示在合并后的单元格中。将丢弃任何其他值或公式,那么如何在新的空白单元格中将两行数据合并…

基于FPGA的按键消抖

文章目录 基于FPGA的按键消抖一、按键消抖原理二、按键消抖代码三、仿真代码编写四:总结 基于FPGA的按键消抖 一、按键消抖原理 按键抖动:按键抖动通常的按键所用开关为机械弹性开关,当机械触点断开、闭合时,由于机械触点的弹性…

Makefile学习笔记

Makefile思想: 一个简单的 Makefile 文件包含一系列的“规则”,其样式如下: 目标:依赖 tab命令 例如: test : main.c sub.c sub.h gcc -o test main.c sub.c如果“依赖文件”比“目标文件”更加新,那么执…

如何保证消息的可靠性+延迟队列(TTL+死信队列+延迟队列)

目录 1.如何保证消息的可靠性 1.1.消息的可靠投递 confirm机制 return机制 1.2.如何保证消息在队列中不丢失 1.3.确保消息能可靠的被消费掉 2.延迟队列 2.1.TTL 2.2.死信队列 2.3.延迟队列 3.如何防止消费者重复消费消息 1.如何保证消息的可靠性 1.1.消息的可靠投递…

Ajax详解

文章目录 1. 概述1.1 Ajax工作原理1.2 Ajax的作用1.3 同步异步 2. 原生Ajax3. Axios3.1 Axios的基本使用3.2 Axios快速入门3.3 请求方法的别名 1. 概述 Ajax 是 “Asynchronous JavaScript and XML”(异步 JavaScript 和 XML)的缩写。它是一种在无需重新…

RabbitMQ知识掌握 【进阶篇】

一、如何保证消息的可靠性 🍉 1.保证消息的可靠性投递 🥝 在生产环境中由于一些不明原因,导致 rabbitmq 重启,在 RabbitMQ 重启期间生产者消息投递失败,导致消息丢失,需要手动处理和恢复。于是&#xff0…

微服务Gateway网关(自动定位/自定义过滤器/解决跨域)+nginx反向代理gateway集群

目录 Gateway网关 1.0.为什么需要网关? 1.1.如何使用gateway网关 1.2.网关从注册中心拉取服务 1.3.gateway自动定位 1.4.gateway常见的断言 1.5.gateway内置的过滤器 1.6.自定义过滤器-全局过滤器 1.7.解决跨域问题 2.nginx反向代理gateway集群 2.1.配置…

什么是 TCP 和 UDP?Java 中如何实现 TCP 和 UDP 协议

在计算机网络中,TCP(传输控制协议)和UDP(用户数据报协议)是两种最常用的传输层协议。它们都用于在网络上传输数据,但是它们之间有很多不同之处。本文将介绍TCP和UDP的基本概念,以及在Java中如何…

ubuntu20.04配置vscode

下载: https://az764295.vo.msecnd.net/stable/660393deaaa6d1996740ff4880f1bad43768c814/code_1.80.0-1688479026_amd64.debhttps://az764295.vo.msecnd.net/stable/660393deaaa6d1996740ff4880f1bad43768c814/code_1.80.0-1688479026_amd64.deb 安装&#xff1a…