向量数据库|第2期|pgvectorscale

向量数据库|第2期|pgvectorscale

大家都听说过pgvector,一个PostgreSQL存储和查询向量的扩展,是PG AI生态当之无愧的最受推崇的工具之一。pgvector向PG中添加了vector类型,以及各种搜索操作符和索引,使其拥有vectors和metadata的完整数据库能力。但他的HNSW索引有两个问题:

1)需要将整个索引都放到内存,否则会变慢。索引成为整个应用的唯一瓶颈

2)基于HNSW索引的search不能以一种合理的方式充分利用预过滤。利用HNSW查询向量首先需要进行索引查询、获取结果,然后才能进行过滤。更为糟糕的是,HNSW仅能从search中返回最大结果集(大多数情况下小于 1,000,否则会变得很慢)。假设你有一个多租户应用,维护数千支teams,每一个有数千个文本(或向量)。针对你的查询请求,HNSW会查询所有vectors,返回一个有限数量的结果集,然后在此结果集上执行过滤。如果最佳结果位于不相干team中时,无法保证为你的team找到任何向量。

pgvectorscale(Rust语言开发的)添加了基于磁盘的流索引,可以解决这两个问题。准确的说,它添加了微软DiskANN论文中提到的StreamingDiskANN,一种图结构的专门用于过滤的近邻查询的索引。

pgvectorscale的三大特性:支持DiskANN索引(算法)、支持streaming post-filtering、支持SBQ(statistical binary quantization)。

1、DiskANN算法

DiskANN算法和HNSW类似也是一种基于图的查询算法。基于图的算法有一个问题:查找一个距离start position非常远的点非常耗时,因为它需要大量hops。

HNSW通过引入一个分层系统(顶层仅有“long-range”边,即高速公路边,帮助快速进入正确的区域,并且有指向低层节点的指针允许以更细粒度的遍历图)。该方法虽然解决了Long-range问题,但通过分层系统引入了更多的indirection,需要更多随机访问,从而需要将该图放到RAM中以获得更好的性能。

与此相反,DiskANN使用单层图,在图构建时通过引用远距离的邻居边来解决long-range问题。单层构建简化了算法,并且在查询时减少了不必要的随机访问,使得SSD更加高效。

相对于HNSW来说,它从一个随机图开始,他的核心是一个名为Vamana的图ANN算法,即构建图的算法为

1)随机初始化一个出度为R的图G:每个节点随机选择R数量的邻居节点并建立连接

2)计算图G的导航点,也就是近似质心

3)以距离全局质心最近的点作为搜索算法起始节点,为每个点重新选择近邻

4)基于步骤1初始化的随机近邻图和步骤3确定的起始点,对每个点做GreedySearch即贪婪搜索,将搜索路径上的所有点都放到近邻集。这里需要跳到1.1和1.2部分了解如何选择候选邻居集。

5)执行步骤3)和4)两遍,第一遍α=1,第二遍α>=1。

其实是,在随机图基础上,从质心开始遍历两遍重新生成新图。

如何体现Disk?

对于索引构建的问题,DiskANN 在构建索引时通过 k-means 聚类的方式将整个数据集划分成 k 个簇,然后将每个节点分配到最近的 l 个簇中,每个簇分别构建 Vamana 图,这样就可以在内存中进行索引的构建,最后通过简单的边并集将所有不同的图合并为一个图。

1.1如何选择近邻?

4b58be5e7aaecea30a515b756061e1f2.png

现有的一些近邻图算法选边策略:如上图给绿色点选择邻居,假设要给它选择两个邻居,从构建一个精确的近邻图角度来看,一定是选择离绿色点最近的两个点(点1和点2)。这样得到的图精确了,但是可能造成邻居集中在一块的现象,不能在各个方向均匀分布。DiskANN论文中提出,一个精确的近邻不并不一定是最合适的ANNS。

因此可以通过连接远距离的点来构建近邻图:先将距离绿色点最近的点1选中(加入绿色点的近邻集),然后对点2进行判断:if d(1,2) < d(2,绿点),则不将点2加入绿色点的近邻集。其中d表示两点的距离。依次对3及左下角的其他点进行判断(顺序是离旅店由近到远),最后判断点4,d(4,1)>d(4,绿点),所以将4加入绿点的近邻集。

这种方法比较激进,会删除很多长边。

1.2如何调整,再增加一些长边?

78fde37a30c90950c37b698fed5bca25.png

一种极端情况下,数据集中的点都在一条线上,如上图。如此按照1.1进行选边时,每个点只能和离它最近的两个点相连。这样执行ANNS时,会导致平均跳数很高,如果配合外村执行搜索,可能会导致多次磁盘IO。a距离b最近,将a加入b的近邻;接着判断c,d(a,c)>d(b,c),c加入b的近邻;直线上的其他点就如同被a和c屏蔽掉一样,不和b相连了,因为d(a,其他)<d(b,其他)或者d(c,其他)<d(其他)。

Vamana对此进行了调整,增加一个参数α:α*d(a或者c,其他)>d(b,其他),通过调整α值,从而增加一些长边。

2、streaming post-filtering

很多时候,搜索语义相似的条目时,希望额外加上过滤条件进行限制。比如文档通常和一组标签相关联,希望通过请求匹配的标签以及向量相似性来限制搜索。

6a056813d4abb402f9fe8b5ccfef9a5f.png

tow-stage post-filtering的问题:做近似近邻搜索时,选了比如top 5个,但是这几个都没有落在匹配的集合中,那么过滤后,就会返回错误的结果。

很多基于HNSW的索引包括pgvector中的实现,若检索集中没有足够多的条目与条件匹配,那么就可能结果严重失真。

b9cdb257b7e348e6c65a466c679430e5.png

从图中就可以清晰看出,它加了个get_next()函数,会持续进行调用,直到得到正确个数的记录。

3、新的量化算法:statistical binary quantization

许多向量索引使用压缩来减少向量存储所需的空间,并使索引遍历更快,但代价是精度有所损失。常见的算法有乘积量化(PQ)和二进制量化(BQ)。Pgvector在0.7.0版本中对HNSW索引添加了BQ。

BQ压缩算法以一种非常简单的方式将浮点向量转换成二进制向量:对于向量中的每个元素,如果该值大于0.0,则将二进制值设置成1,否则设置成0.然后距离函数就变成了XOR函数。为什么是异或?我们可以这么理解,二进制向量将空间分成下图的象限,异或函数计算从一个象限到另一个象限需要穿过多少个平面:

beaa5475f6a87497b020e931c20e6398.png

每个浮点维度转换为两位(我们后来将其推广)。这个想法是使用平均值和标准差来导出 z 分数(一个值与通过标准偏差归一化的平均值的距离),然后将 z 分数分为三个区域。然后,我们将这三个区域编码为两位,使得相邻区域的 XOR 距离为 1,并且距离随着 z 分数距离的增加而增加。在具有三个区域的两位情况下,编码为 00、01、11。

通过实验,我们发现两位编码确实有助于提高 768 维情况下的准确性。因此,默认情况下,我们对任何小于 900 维的数据使用两位编码,否则使用一位编码。在 768 维数据集的一个代表性示例中,当从一位编码切换到两位编码时,召回率从 96.5% 提高到 98.6%,在如此高的召回率水平下这是一个显着的改进。

4、参考

https://www.timescale.com/blog/how-we-made-postgresql-as-fast-as-pinecone-for-vector-data/

https://www.timescale.com/blog/how-we-built-a-content-recommendation-system-with-pgai-and-pgvectorscale/

https://github.com/timescale/pgvectorscale/?ref=timescale.com

https://proceedings.neurips.cc/paper_files/paper/2019/file/09853c7fb1d3f8ee67a61b6bf4a7f8e6-Paper.pdf?ref=timescale.com

https://mp.weixin.qq.com/s?__biz=MzkxOTQwNzU0Ng==&mid=2247486484&idx=1&sn=f254f2adbe4d3d3186fd04fdf3e4de5b&chksm=c1a3d2c1f6d45bd758dac5380ffbff2ad97a8ae7f435b4265feadd3fe0fe09c0a43cfc6ca136#rd

https://blog.csdn.net/whenever5225/article/details/106863674

https://dl.acm.org/doi/pdf/10.5555/3454287.3455520

https://mp.weixin.qq.com/s/ynXT945swVVJDFk8UJ-xIQ

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

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

相关文章

【sqlmap使用】

sqlmap简介 sqlmap 目录结构 sqlmap常用参数 sqlmap实现注入 测试注入点&#xff0c;检测到注入点后&#xff0c;直接爆数据库名 python sqlmap.py –u http://172.16.12.2/7/9/strsql.php --data "usernameadmin" --dbs注意sqlmap在使用过程中可能会出现几个需要…

Perl 环境安装

Perl 环境安装 Perl 是一种广泛使用的高级、通用、解释型、动态编程语言。它最初由 Larry Wall 在 1987 年设计,现在由 Perl 5 和 Perl 6 两个主要版本组成。Perl 适合于多种编程任务,包括系统管理、Web 开发、网络编程、游戏开发等。在开始使用 Perl 进行编程之前,您需要在…

通过源码分析类加载器里面可以加载的类

类列表 每一个ClassLoader里面的类列表&#xff0c;类的数量都是固定的。 对上一节中的dex反编译 使用DexClassLoader类动态加载插件dex   利用jadx对dex进行反编译可以看到有哪些类 源码分析 BaseDexClassLoader 从BaseDexClassLoader类加载器开始分析 在BaseDexClassLoade…

力扣11.3

1981. 最小化目标值与所选元素的差 给你一个大小为 m x n 的整数矩阵 mat 和一个整数 target 。 从矩阵的 每一行 中选择一个整数&#xff0c;你的目标是 最小化 所有选中元素之 和 与目标值 target 的 绝对差 。 返回 最小的绝对差 。 a 和 b 两数字的 绝对差 是 a - b 的…

宝塔使用clickhouse踩坑

前言 最近有个物联网项目&#xff0c;需要存储物联网终端发送过来的信息&#xff08;类似log日志&#xff0c;但又要存储在数据库里&#xff0c;方便后期聚合统计&#xff09;&#xff0c;本来想写文件的奈何客户要求聚合统计&#xff0c;所以只能用数据库才能达到更高的计算效…

parted 磁盘分区

目录 磁盘格式磁盘分区文件系统挂载使用扩展 - parted、fdisk、gdisk 区别 磁盘格式 parted /dev/vdcmklabel gpt # 设置磁盘格式为GPT p # 打印磁盘信息此时磁盘格式设置完成&#xff01; 磁盘分区 开始分区&#xff1a; mkpart data_mysql # 分区名&…

NFTScan Site:以蓝标认证与高级项目管理功能赋能 NFT 项目

自 NFTScan Site 上线以来&#xff0c;它迅速成为 NFT 市场中的一支重要力量&#xff0c;凭借对各类 NFT 集合、市场以及 NFTfi 项目的认证获得了广泛认可。这个平台帮助许多项目提升了曝光度和可见性&#xff0c;为它们在竞争激烈的 NFT 市场中创造了更大的成功机会。 在最新更…

统计数据集的TXT、XML及JSON标注文件中各类别/每个标签的数量

在计算机视觉和深度学习领域&#xff0c;标注文件是模型训练的重要组成部分。无论是图像分类、目标检测还是图像分割&#xff0c;正确的标注能够显著提升模型的性能。在实际应用中&#xff0c;我们需要快速了解每个类别的样本数量&#xff0c;以便进行数据分析、平衡类别分布或…

leetcode-5-最长回文子串

题解&#xff1a; 回文串&#xff1a;如果一个字符串正着读和反着读都是一样的那这个字符串就是回文串。 对于一个子串而言&#xff0c;如果它是回文串&#xff0c;并且长度大于 2&#xff0c;那么将它首尾的两个字母去除之后&#xff0c;它仍然是个回文串。 1、初始化字典d…

深入了解 Flutter 中的泛型:让代码更灵活更安全的关键

目录 前言 一、泛型类 二、泛型方法 三、泛型约束 四、Flutter 中泛型的实际应用 前言 泛型&#xff08;Generics&#xff09;是编程语言中一种关键机制&#xff0c;它允许我们在类、接口、方法等结构中使用类型参数&#xff0c;而不必指定具体的类型。在 Flutter 中&…

移动混合开发面试题及参考答案

目录 什么是混合开发(Hybrid App)? 混合开发(Hybrid App)与原生开发相比有什么优缺点? 优点 缺点 混合开发(Hybrid App)的兴起原因是什么? 市场竞争和成本控制需求 技术发展和资源整合 人才资源的考量 Web App、Native App 和混合开发(Hybrid App)的区别是…

mysql5安装

1.下载安装包 https://downloads.mysql.com/archives/community/ mysql-5.7.44-1.el7.x86_64.rpm-bundle.tar tar -xvf mysql-5.7.44-1.el7.x86_64.rpm-bundle.tar2.安装依赖 yum -y install perl yum -y install net-tools yum install numactl libaio libaio-devel -y也可…

【工具变量】“宽带中国”试点城市名单匹配数据集(2000-2023年)

参照秦文晋&#xff08;2022&#xff09;的《网络基础设施建设对数字经济发展的影响研究——基于"宽带中国"试点政策的准自然实验》一文中的做法&#xff0c;将选为“宽带中国”试点城市的虚拟变量作为核心解释变量&#xff0c;当一个城市被批复成为“宽带中国”试点…

php内置服务停止shell小工具,用来停止指定的端口的php内置服务进程

最近vscode总是喜欢闪退&#xff0c;这导致了上面启动的php内置服务变成了无法管理状态&#xff0c;所以就有了这个工具来停止相关的PHP内置服务进程. 将下面的代码保存到本地合适的位置&#xff0c;并命名为 stop.sh #!/bin/bash # Author: tekintian # Date: 2024-11-02 …

Servlet 3.0 注解开发

文章目录 Servlet3.0注解开发修改idea创建注解的servlet模板内容讲解 关于servlet3.0注解开发的疑问_配置路径省略了属性urlPatterns内容讲解内容小结 Servlet3.0注解开发 【1】问题 说明&#xff1a;之前我们都是使用web.xml进行servlet映射路径的配置。这样配置的弊端&…

力扣每日一题——数组能够形成多少对

目录 题目链接&#xff1a;2341. 数组能形成多少数对 - 力扣&#xff08;LeetCode&#xff09; 题目描述 解法一&#xff1a;List集合 Java写法&#xff1a; 运行时间 C写法&#xff1a; 解法二&#xff1a;Set集合 Java写法&#xff1a; 运行时间 C写法 上述两种方法…

开源项目-投票管理系统

哈喽,大家好,今天主要给大家带来一个开源项目-投票管理系统 投票管理系统主要有首页,发起投票,管理投票,参与投票,查看投票等功能 首页 为用户提供了一键导航到各个功能模块的便捷途径。 新增投票 用户可以在此轻松创建新的投票活动,设置投票主题、选项等信息。 管理…

高级java每日一道面试题-2024年10月27日-Redis篇-jedis和redisson有哪些区别?

如果有遗漏,评论区告诉我进行补充 面试官: jedis和redisson有哪些区别? 我回答: 在Java高级面试中&#xff0c;Jedis和Redisson的区别是一个常见且重要的话题。以下是对这两个Java客户端库的详细对比&#xff1a; 设计思想与实现方式 Jedis&#xff1a; 设计思想&#xff…

[Python]K小姐经营着一家蛋糕店,她的蛋糕店有 n 种口味的蛋糕。这 n 种口味的蛋糕在 A 工厂和 B 工厂都有生产。

问题来源&#xff1a;【秋招突围】2024届秋招-京东笔试题-第三套_牛客网 问题描述 K小姐经营着一家蛋糕店&#xff0c;她的蛋糕店有 n种口味的蛋糕。这 n 种口味的蛋糕在 A 工厂和 B 工厂都有生产。 对于每种口味的蛋糕&#xff0c;如果 A 工厂生产的口感值为 AiA_iAi​&…

设计模式讲解01-建造者模式(Builder)

1. 概述 建造者模式也称为&#xff1a;生成器模式 定义&#xff1a;建造者模式是一种创建型设计模式&#xff0c;它允许你将创建复杂对象的步骤与表示方式相分离。 解释&#xff1a;建造者模式就是将复杂对象的创建过程拆分成多个简单对象的创建过程&#xff0c;并将这些简单…