pgvector 源码分析

news2024/11/25 8:16:07

简介

pgvector 库是一种用于计算向量距离的库,它的核心是提供了聚类索引,棸类索引使用的算法是 kmeans++(相对于 kmeans 最主要的区别是初始化起点的位置)。

pgvector 索引的存储结构

meta page → list page → entry page

请添加图片描述

insert page 是最后一页,当发生过 vacuum 后它会指向第一个回收了 tuple 的页,下一次插入 indextuple 从这个页开始

对pgvector 来说,keys 是点的向量值

索引创建过程

用户创建时指定计算距离的方法(ivfflat 的参数)与棸类中心的数量(lists)

CREATE INDEX ON t USING ivfflat (val) WITH (lists = 1);

build 过程: 计算中心节点-》创建meta/list页-》填充entry页

计算中心节点

1、初始化中心节点

使用 kmeans++ 算法:假设要聚n类

  • 采集一定的样本点(50×n个),
  • 随机选1个点作启动点,计算每个点到这个中心点的距离
  • 以每个点到这个中心点的距离为权重,重新筛选出一个点作为新的初始中心(认为离最近棸类中心最远的点,最可能成为棸类中心,InitCenters),总共选出n个新初始中心

2、计算每个中心点相对最近中心点的距离,检查是否所有其它点到中心点x的距离小于中心点x与最近中心y之间的距离

3、对大于中心点间距离的点,重新找到离它最近的中心点,加入对应的簇

4、重新计算每个簇的中心点(计算所有簇内点每个维度的平均值作为第一维度的值,并对这个算出来的点的所有维度做统一正则化)

5、计算新中心与老中心的距离,把这个距离更新到每个点与中心的距离的上下界上(因为d(x,old) c- d(old,new) < d(x,new) < d(x,old) + d(old,new) )

6、循环至棸类中心不再变

填充entry页

1、起并行 worker 去扫描每个 tuple 做棸类(AssignTuples)

2、由 leader 去合并每个 worker 的 tap,合并的过程实际是对每个点属于的簇号作排序(tuplesort_performsort),未对簇内的 vector 做排序

3、为每个簇(list)插入实际的 indextuple(InsertTuples),index key 是 点向量值

worker的并行度

worker的并行度取决于用户对源表 set 的 rel_parallel_workers,用户未指定时,并行度为 log3(表的页数),并且要满足每个 worker 可以分到 32m 内存,用户未配置的情况下,为worker分配的总默认内存为64m(默认无法并行worker,因为master + worker至少要64m)。

sort 的执行

索引的scan

1、找每个聚簇中心,计算中心与目标点的距离,利用堆排序找出最近的 topN 中心,N取决于用户设置的ivfflat.probes。(GetScanLists)

2、去中心点簇对应的entry页,一页页找取点算距离,最后sort 一下(GetScanItems)

3、后面就可以一条条tuplesort_gettupleslot了(index 的数据不会删除,依赖于 postgresql 的 HOT 机制,真正删除发生在 vacuum 中)

vacuum

vacuum 时遍历 list/entry 页,看是否在 vacuum 普通表时已经 vacuum 过 tuple(lazy_record_dead_tuple),如果删除过,则收集这个 indextuple,最后执行页的vacuum并记 xlog,并更新下一个 insert page number(相当于回收tuple 位置)

这里有个细节,第一次 delete 一页的 tuple 时,要记一个 copy(GenericXLogRegisterBuffer),每次记录delete tuple位置时,要从这个 copy 中去记录 delete 的位置,最后一并执行 delete(pg给的接口是这样的)

cost 计算

page cost

计算随机访问 index page 的 cost:根据扫描的输出的点数(ivfflat.probes),估算扫描的 tuple 数,再根据 index 过滤条件,判断扫描出的 index tuple 数,进而算出扫描 index 页数,从而得到 random 访问的 index page 的 cost

如果是 join 的 inner 部分,总共访问 index page cost 要乘上 loop_count,然后再考虑 cache 带来的 cost 消除,这部分公式有点复杂,可以不看

∣ p a g e _ f e t c h ∣ = { m i n ( 2 ∗ p a g e ∗ t u p l e ∗ f r a c 2 ∗ p a g e + t u p l e ∗ f r a c , p a g e ) p a g e ≤ t u p l e 2 ∗ p a g e ∗ t u p l e ∗ f r a c / ( 2 ∗ p a g e + t u p l e ∗ f r a c ) p a g e > t u p l e , t u p l e ∗ f r a c < = 2 ∗ p a g e ∗ b u f 2 ∗ p a g e − b u f b u f + ( t u p l e ∗ f r a c − 2 ∗ p a g e ∗ b u f 2 ∗ p a g e − b u f ) ∗ ( p a g e − b u f ) p a g e p a g e > t u p l e , t u p l e ∗ f r a c > 2 ∗ p a g e ∗ b u f 2 ∗ p a g e − b u f |page\_fetch| = \begin{cases} min(\frac{2*page*tuple*frac}{2*page+tuple*frac} ,page) &\quad page \leq tuple \\ 2*page*tuple*frac/(2*page+tuple*frac) &\quad page \gt tuple , tuple * frac <= \frac{2*page*buf} { 2*page-buf} \\ buf + \frac{(tuple*frac - \frac{2*page*buf}{2*page-buf})*(page-buf)}{page} &\quad page \gt tuple , tuple * frac > \frac{2*page*buf} { 2*page-buf} \end{cases} page_fetch= min(2page+tuplefrac2pagetuplefrac,page)2pagetuplefrac/(2page+tuplefrac)buf+page(tuplefrac2pagebuf2pagebuf)(pagebuf)pagetuplepage>tuple,tuplefrac<=2pagebuf2pagebufpage>tuple,tuplefrac>2pagebuf2pagebuf

index 默认是 random 访问的,random 访问的代价是 sequence 访问的四倍,而实际实现的访问是 seq 访问的,所以减去 seq 与 random 访问的差值。

这个过程中,如果点 vector 的维度很大,导致用 toast 类型来存 index(现象是算的 index page 访问数比 index 实际 page 数高,说明 index 是 toast 存储,因为 toast 存储不记录为 index 页),这个时候,要记得减去 toast 页算出的随机访问 cost。

cpu cost

  • where 条件本身 cost,order by 条件本身 cost
  • cpu_index_tuple_cost + cpu_operator_cost × (where 条件数 + order by 数) * tuple 数

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

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

相关文章

vue2和vue3关于class类的绑定以及style的绑定的区别

本篇为个人笔记 1.对于class类的绑定的区别 vue2:对于vue2而言&#xff0c;所有类的绑定都是基于对象{}来进行的 例如&#xff1a;单个类绑定 <div :class"{active:isActive}"></div> 多个类绑定&#xff1a; <div :class"{active,hasError…

CNN(卷积神经网络)的实现过程详解

概要 在图像处理领域&#xff0c;CNN(卷积神经网络)处于绝对统治地位&#xff0c;但对于CNN具体是如何用神经网络实现的&#xff0c;能找到的介绍要么是一大堆数学公式&#xff0c;要么是大段晦涩的文字说明&#xff0c;读起来很是辛苦&#xff0c;想写好一片完整的而且有深度的…

【java安全】RMI

文章目录 【java安全】RMI前言RMI的组成RMI实现Server0x01 编写一个远程接口0x02 实现该远程接口0x03 Registry注册远程对象 Client 小疑问RMI攻击 【java安全】RMI 前言 RMI全称为&#xff1a;Remote Method Invocation 远程方法调用&#xff0c;是java独立的一种机制。 RM…

软件检测报告CMA/CNAS标识加盖和不加盖的区别在哪?

在生活中&#xff0c;我们经常会听到CMA(中国计量认证)和CNAS(中国合格评定国家认可委员会)这两个标识&#xff0c;尤其在软件检测领域更是如此。那么&#xff0c;软件检测报告CMA/CNAS标识加盖和不加盖有哪些区别呢CMA和CNAS认可的软件测评机构又有什么样的好处呢?本文将为您…

各电商平台api接口开发系列(数据分享)接口封装高并发

淘宝API接口就是第三方公司&#xff0c;通过淘宝开放平台接入淘宝数据&#xff0c;并进行再开发&#xff0c;将功能封装打包成函数&#xff0c;客户只需要传入参数&#xff0c;接收返回值就可以实现具体功能&#xff0c;其他1688&#xff0c;京东&#xff0c;拼多多以及海外跨境…

[Android 13]Input系列--触摸事件在应用进程的分发和处理

hongxi.zhu 2023-7-21 Android 13 前面我们已经梳理了input事件在native层的传递&#xff0c;这一篇我们接着探索input事件在应用中的传递与处理&#xff0c;我们将按键事件和触摸事件分开梳理&#xff0c;这一篇就只涉及触摸事件。 一、事件的接收 从前面的篇幅我们知道&…

STM32CubeMX v6.9.0 BUG:FLASH_LATENCY设置错误导致初始化失败

背景 今天在调试外设功能时&#xff0c;发现设置了使用外部时钟之后程序运行异常&#xff0c;进行追踪调试并与先前可以正常运行的项目进行对比之后发现这个问题可能是由于新版本的STM32CubeMX配置生成代码时的BUG引起的。 测试环境 MCU: STM32H750VBT6 STM32CubeIDE: Versi…

Android 屏幕适配各种宽高比的手机

由于android 手机的屏幕宽高比样式太多了&#xff0c;在设计UI时&#xff0c;很多时候&#xff0c;会因为宽高比&#xff0c;分辨率不同会有展示上的差异。 我是这样解决的 在activity的onCreate方法前&#xff0c;调用&#xff1a; fun screenFit(context: Context) {val me…

Gitee 上传项目到仓库(上传文件夹)

一、将仓库下载到本地 1.首先打开仓库&#xff0c;点击下载压缩包 2.将下载的压缩包解压&#xff0c;并打开&#xff0c;在当前目录下打开 二、git操作 1.在文件当前目录打开git bash 2.初始化git git init 该命令会生成一个隐藏的.git文件夹 如果不是第一次使用&#…

自然语言处理14-基于文本向量和欧氏距离相似度的文本匹配,用于找到与查询语句最相似的文本

大家好&#xff0c;我是微学AI&#xff0c;今天给大家介绍一下自然语言处理14-基于文本向量和欧氏距离相似度的文本匹配&#xff0c;用于找到与查询语句最相似的文本。NLP中的文本匹配是指通过计算文本之间的相似度来找到与查询语句最相似的文本。其中一种常用的方法是基于文本…

MybatisPlus使用排序查询时,将null值放到最后

1用户需求 查询结果&#xff0c;按照某些字段进行排序&#xff0c;将为null的值放到最后。按照更新时间排序&#xff0c;但是更新时间可能为null&#xff0c;因此将null的数据放到最后。 2解决方案 最简单的方式&#xff0c;当然是下面这种直接在SQL最后面 NULLS LAST &…

FAPI,2471983-20-5,放射性示踪剂成纤维细胞激活蛋白抑制剂显像剂

资料编辑|陕西新研博美生物科技有限公司小编MISSwu​ 一、产品描述&#xff1a; 成纤维细胞激活蛋白抑制剂显像剂FAPI&#xff08;CAS号&#xff1a;2471983-20-5&#xff09;&#xff0c;FAPI是一种放射性示踪剂&#xff0c;全称为成纤维细胞活化蛋白抑制剂。为小分子酶活性抑…

elasticsearch操作(API方式)

说明&#xff1a;es操作索引库、文档&#xff0c;除了使用它们自带的命令外&#xff08;参考&#xff1a;http://t.csdn.cn/4zpmi&#xff09;&#xff0c;在IDEA中可以添加相关的依赖&#xff0c;使用对应的API来操作。 准备工作 搭建一个SpringBoot项目&#xff0c;DAO使用…

为什么 Linux 内核协议栈会丢弃 SYN 数据包

最近了解到 SYN 数据包丢弃的问题&#xff0c;网上有一些资料&#xff0c;这里记录分享一下。 serverfault上的重要信息 tcp - No SYN-ACK Packet from server - Server Fault 信息如下&#xff1a; My embedded system with LwIP is the client and I have server1 and ser…

微信小程序开发,小程序类目符合,线上版本无权限申请wx.getLocation接口

我开发 的小程序类目符合wx.getLocation接口的申请标准 但是却还是显示无权限申请 后来研究好久才发现&#xff0c;小程序需要在发布线上版本时提交用户隐私保护指引 如未设置也可以在 设置-服务内容声明-用户隐私保护指引-声明处理用户信息项并补充填写后提交用户隐私协议审核…

MURF20100CTR-ASEMI快恢复对管封装、尺寸、参数

编辑&#xff1a;ll MURF20100CTR-ASEMI快恢复对管封装、尺寸、参数 型号&#xff1a;MURF20100CTR 品牌&#xff1a;ASEMI 芯片个数&#xff1a;2 芯片尺寸&#xff1a;102MIL*2 封装&#xff1a;TO-220F 恢复时间&#xff1a;50ns 工作温度&#xff1a;-50C~150C 浪…

k8s集群环境的搭建

1.环境规划 1.1 集群类型 Kubernetes集群大致分为两类&#xff1a;一主多从和多主多从。 一主多从&#xff1a;一个Master节点和多台Node节点&#xff0c;搭建简单&#xff0c;但是有单机故障风险&#xff0c;适合用于测试环境。 多主多从&#xff1a;多台Master和多台Node节点…

CMU 15-445 -- Two Phase Locking - 14

CMU 15-445 -- Two Phase Locking - 14 引言Lock TypesTwo-Phase LockingDeadlock Detection & PreventionDeadlock DetectionDeadlock PreventionHierarchical Lockingintention locks加锁协议 锁升级最佳实践显式加锁的相关SQL语句小结 引言 本系列为 CMU 15-445 Fall 2…

剑指offer(C++)-JZ15:二进制中1的个数(算法-位运算)

作者&#xff1a;翟天保Steven 版权声明&#xff1a;著作权归作者所有&#xff0c;商业转载请联系作者获得授权&#xff0c;非商业转载请注明出处 题目描述&#xff1a; 输入一个整数 n &#xff0c;输出该数32位二进制表示中1的个数。其中负数用补码表示。 数据范围&#xf…

【运维】DevOps全流程笔记(未完成)

运维笔记 DevOps基本流程Code阶段工具&#xff08;gitlab安装&#xff09;Build阶段工具&#xff08;Maven安装&#xff09;Integrate阶段工具JenkinsJenkins介绍Jenkins安装Jenkins入门配置 CI/CD操作集成Sonar Qube集成HarborJenkins流水线Kubernetes编排工具 DevOps全流程笔…