数据检索:倒排索引加速、top-k和k最邻近

news2024/11/26 13:56:54

之前在https://www.yuque.com/treblez/qksu6c/wbaggl2t24wxwqb8?singleDoc# 《Elasticsearch: 非结构化的数据搜索》我们看了ES的设计,主要侧重于它分布式的设计以及LSM-Tree,今天我们来关注算法部分:如何进行检索算法的设计以及如何加速倒排索引。然后看看topk的面试热门题如何解决。

状态检索:bitmap的哈希函数公式

bitmap的最优hash函数的计算公式为:
k = (m/n)*ln2
其中m为bit数组的长度,n为要存入的对象个数。

加速倒排索引和Roaring Map

倒排索引由key和posting list构成,posting list可以用很多结构实现,比如红黑树、跳表、链表等。
posting list往往会用于归并过程(join),这里我们很容易想到spark的join策略:嵌套循环、排序归并和哈希归并。他们的复杂度分别是m*n,m+n和n(较大)。
因为posting list天生有序,所以这里主要的策略在于加速排序归并和哈希归并过程。
排序归并可以用跳表和红黑树,双指针相互二分查找将每次搜索的复杂度降低到logk。
Lucene和Elasticsearch就采用了这种方法。
同样,posting list也可以使用哈希表和位图来实现。
普通的哈希表和位图很简单,不再赘述。更广泛使用的是Roaring Bitmap(压缩位图)。
Roaring Bitmap简单来说,就是用高16位哈希到桶的编号,低16位再哈希到bitmap,这样如果元素稀疏的话,就能节省没有bitmap的桶的空间。
低16位桶的数量如果少于4096,那么bitmap就使用数组容器来节省空间,否则使用位图容器。

倒排索引的更新

倒排索引的更新主要有如下方案:

  1. Double Buffer双缓冲 + 原子swap
  2. 全量索引+增量索引

增量索引的合并方案:

  1. 全量合并
  2. 再合并(归并合并)
  3. 滚动合并(加入索引级别)

精准打分和非精准打分

精准打分就是采用堆排序算法进行排序。
复杂度是n+klogn。
非精准打分一般用在召回阶段,也就是排序的第一步,一般采用的打分算法有tf-idf和bm25两种。
那么非精准的打分如何实现呢?

  1. 静态质量得分截断(比如使用pagerank)
  2. 词频得分打分截断(使用胜者表解决相同文档得分不同的情况,选出多于k个结果)
  3. 使用分层索引,建立精准索引和非精准索引,不足k个精准结果去非精准索引中补齐

日志的分布式拆分

索引的拆分方式:

  1. 基于文档进行拆分
  2. 基于前缀进行拆分

※最近的k个人和k最邻近

KNN - 检索最近的k个设施(低维空间的k最近邻)- 四/八叉树、前缀树和k-d树

这两个问题都可以用Geohash编码,但是k最邻近设施比k个人更加复杂。
最近的k个人只需要查找编码的附近8个区域,就可以转换到非精确打分 – > 精确打分的流程中,但是k最邻近则需要不断扩大搜索范围,每次扩大一个搜索层级进行搜索。
为了利用到之前搜索的结果,k最邻近可以使用四叉树(二维),前缀树、八叉树(三维)和k-d树。
检索最近的k个加油站、检索相似文章都是这类问题,相似文章在存储中表示为n维向量中的一个点,也会变成k最邻近设施的问题。

ANN - 过滤相似文档(高维空间的k最近邻)- 局部敏感哈希

当向量的维度太高的时候,k-d树的复杂度会变得很高。这时候,我们会采用局部敏感哈希的方案来处理:
对于高维空间,局部敏感哈希会随机生成n个超平面,每个平面都会将高维空间划分成两个部分,分别编码为0和1,如果有两个点的哈希值的海明距离比较小,那么我们就认为它们邻近。
局部敏感哈希的问题在于它无法保存每个维度的权重信息,Google提出了SimHash来解决这个问题。

ANN - 有权重的高维空间k最近邻-SimHash

simHash会将哈希函数编码中的0和1转换为-1和1,并且乘上权重值,最后将所有关键词的哈希值相加。最后将大于0的值变为1,小于等于0的值变为0.
那么如何在这个基础上进行相似检索呢?
简单的方法是将每一个比特位都当作索引,在召回时分别考虑自己的每一个比特位,进行召回,但是这样产生的数据量很大,google提出的解决方案是抽屉原理:将哈希值平均切为4段,如果两个哈希值的比特位差异不超过3个(海明距离小于等于3),那么至少有一个段的比特位完全相同。
因此,我们可以将每一个文档都根据比特位分为4段,建立4个倒排索引,然后进行召回。

ANN - HNSW

Delaunay图可以保证图中所有的点都有点与之相连,且能保证整张图的边的数量尽可能的少。但实际上,NSW并不是直接采用Delaunay图。Delaunay图有个缺点,它没有高速公路机制,也就是说所有的图节点都只会跟自己相近的点建立连接,如果需要抵达一个距离较远的点,则时间复杂度较高。而不管是构建图索引的时候,还是在线检索的时候,都需要进行临近搜索,直接采用Delaunay图就会导致离线索引构建以及在线serving的时间复杂度不理想。
NSW的图结构是近似的Delaunay图,与Delaunay图不同的是,他有高速公路机制。如图所示。
image.png

拍照识花–乘积量化

上面的ANN和KNN算法的问题在于,它们只能用在表面特征的相似性上,而不是本质的相似性上。
在需要本质相似性的领域,比如图像处理上,需要KMeans来进行聚类。
K-means可以将k个聚类id作为倒排索引的key来建立倒排索引。
当要查询一个点邻近的点时,计算该点和所有聚类中心的距离,就可以进行topK的查询。
为了优化存储空间,可以用乘积量化技术进行压缩。

LevelDB的lsm-tree

LevelDB将内存数据分为memtable和immutable table两部分。这两部分数据都使用跳表存储。
当memtable的数据达到存储上限时,将会被转换为immutable table,并且生成一个新的memtable,新的memtable被用来支持新数据的写入和读取。immutable只读,不需要加锁就能写入磁盘。
LevelDB使用LCS(https://www.yuque.com/treblez/qksu6c/wbaggl2t24wxwqb8#seDXd)进行合并,从第一层开始使用归并排序后的结果。
SSTable分为数据存储区(data block)和数据索引区(index block)。
数据索引区从上到下又分为:

  • 过滤器数据区
  • 过滤器索引区
  • 数据索引区 对数据存储区的block进行索引 格式 key - offset - size
  • foot block 记录index block和meta index block的大小

SSTable的检索过程和列式存储很像,这里的过滤器都是bloom filter。
使用缓存加速检索SSTable文件的过程
如果在二分查找时,将data block和index block分两次io读入内存,那么开销显然非常大,为了减少这里的开销,LevelDB设计了table cache和block cache两个索引。
table cache存储最近使用的SSTable的index block,block cache存储最近使用的data block。这两个缓存都使用LRU策略替换。
levelDB的一个问题在于如果immutable table还没有写入磁盘,memtable满了,会导致阻塞,google的rocksDB允许创建多个memtable解决了这个问题。
B+树适用于随机读很多,但是写入很少的场景;lsm树进行了大量写操作优化,效率会更高。
在LSM-Tree的L0写入时,限制文件数量,L1及以上则要限制容量大小;写入时会根据beg和end限制本层的一个sstable文件在下一层对应的sstable文件数小于十个,如果达到了十个就会结束文件的生成。

top-k + lsm-tree

TOP-K一直是面试的热门题目,题目的意图一般是考察小/大顶堆或者快速选择算法。
我们来考虑更复杂的情况:

  1. 有插入和删除的top-k中,什么样的数据结构/算法是最合适的?
  2. 面对海量数据的存储,在不使用swap mem的情况下,怎样实现top-k?
  3. 用ES怎么实现top-k?复杂度如何?
  4. 流式数据的top-k又如何实现?

https://blog.quarkslab.com/mongodb-vs-elasticsearch-the-quest-of-the-holy-performances.html

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

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

相关文章

RapidMiner数据挖掘2 —— 初识RapidMiner

本节由一系列练习与问题组成,这些练习与问题有助于理解多个基本概念。它侧重于各种特定步骤,以进行直接的探索性数据分析。因此,其主要目标是测试一些检查初步数据特征的方法。大多数练习都是关于图表技术,通常用于数据挖掘。 为此…

嵌入式系统中常见传感器介绍

(本文为简单介绍,内容取材网络) 传感器是嵌入式系统接入外部环境信息的重要接口,根据测量物理量的不同,传感器可以分为温度传感器、湿度传感器、压力传感器、加速度传感器等多种类型。选择合适的传感器,对于实现嵌入式系统的控制和互动功能至…

Java微服务架构的选择:Spring Cloud、Kubernetes还是Kubernetes + Istio?

微服务架构已经成为现代软件开发的趋势,其可以带来高度可伸缩性、松耦合性和团队自治性等优势。 在Java开发领域中,选择适合的微服务架构是非常关键的决策,本文将探讨Spring Cloud、Kubernetes和KubernetesIstio这三个架构选择的优势和劣势。…

MIT-BEVFusion系列八--onnx导出1 综述及相机网络导出

目录 综述export-camera.py加载模型加载数据生成需要导出成 onnx 的模块Backbone 模块VTransform 模块 生成 onnx使用 pytorch 原生的伪量化计算方法导出 camera.backbone.onnx导出 camera.vtransform.onnx 综述 bevfusion的各个部分的实现有着鲜明的特点,并且相互…

BUGKU-WEB 本地管理员

题目描述 题目截图如下: 进入场景看看: 解题思路 老规矩,先看源码发现了,那就要base一下了测试账号密码绕过IP限制 相关工具 F12插件modHeader 或者 直接使用Burp Suit对请求进行修改 解题步骤 先输入admin测试一下 显示…

vue3 中使用pinia 数据状态管理(在Taro 京东移动端框架中的使用)

1.pinia 介绍 pinia 是 Vue 的存储库,它允许您跨组件/页面共享状态。就是和vuex一样的实现数据共享。 依据Pinia官方文档,Pinia是2019年由vue.js官方成员重新设计的新一代状态管理器,更替Vuex4成为Vuex5。 Pinia 目前也已经是 vue 官方正式的…

蓝桥杯2023年第十四届省赛真题

题目 题目描述: 程序猿圈子里正在流行一种很新的简写方法:对于一个字符串,只保留首尾字符,将首尾字符之间的所有字符用这部分的长度代替。例如 internation-alization 简写成 i18n,Kubernetes (注意连字符不…

Javaweb之SpringBootWeb案例之AOP核心概念的详细解析

2.3 AOP核心概念 通过SpringAOP的快速入门,感受了一下AOP面向切面编程的开发方式。下面我们再来学习AOP当中涉及到的一些核心概念。 1. 连接点:JoinPoint,可以被AOP控制的方法(暗含方法执行时的相关信息) 连接点指的…

2.8学习总结

2.8 1.二叉树的前序遍历 2.二叉树的中序遍历 3.二叉树的后序遍历 4.⼆叉树的层序遍历 5.⼆叉树的层序遍历2 6.二叉树的右视图 7.二叉树的层平均值 8.N叉树的层序遍历 9.每个树行中找最大值 10.填充每个节点的下一个右侧节点指针 11.填充每个节点的下一个右侧节点指针2 12.生命之…

C/C++中的max函数如何使用?哪个头文件?多个数字可以用max吗?

在C中&#xff0c;max函数是一个非常实用的函数&#xff0c;它用于比较两个或更多数值并返回其中的最大值。这个函数在头文件中定义。 下面是如何在C中使用max函数的一些示例&#xff1a; #include <iostream> #include <algorithm> // 引入algorithm头文件以使…

【从Python基础到深度学习】 8. VIM两种状态

一、安装 sudo apt install vim 二、VIM两种模式 - 命令状态/编辑状态 1.1 进入/退出VIM 进入VIM vim 退出vim :q <enter> 2.2 根目录下添加配置文件 window下创建vimrc类型文件内容如下&#xff1a; set nu set cursorline set hlsearch set tabstop4 使用Wins…

HTTP协议-响应报文详解(Respond)

目录 前言&#xff1a; 1.Respond报文 1.1报文格式 1.2格式图解 2.状态行&#xff08;首行&#xff09; 2.1状态码/状态码解释 &#xff08;1&#xff09;200 OK &#xff08;2&#xff09;404 Not Found &#xff08;3&#xff09;403 Forbidden &#xff08;4&#…

【LeetCode: 107. 二叉树的层序遍历 II + BFS】

&#x1f680; 算法题 &#x1f680; &#x1f332; 算法刷题专栏 | 面试必备算法 | 面试高频算法 &#x1f340; &#x1f332; 越难的东西,越要努力坚持&#xff0c;因为它具有很高的价值&#xff0c;算法就是这样✨ &#x1f332; 作者简介&#xff1a;硕风和炜&#xff0c;…

红队笔记Day4 -->多层代理(模拟企业拓扑)

声明&#xff1a;本机文章只用于教育用途&#xff0c;无不良引导&#xff0c;禁止用于从事任何违法活动 前几天的红队笔记的网络拓扑都比较简单&#xff0c;今天就来模拟一下企业的真实网络拓扑&#xff0c;以及攻击方法 一般的大企业的网络拓扑如下&#xff1a;&#xff1a;…

【二叉树层序遍历】【队列】Leetcode 102 107 199 637 429 515 116 117 104 111

【二叉树层序遍历】【队列】Leetcode 102 107 199 637 429 515 116 117 102. 二叉树的层序遍历解法 用队列实现107. 二叉树的层序遍历 II解法199. 二叉树的右视图 解法637. 二叉树的层平均值 解法429. N叉树的层序遍历515. 在每个树行中找最大值116. 填充每个节点的下一个右侧节…

vue3-组合式 API

什么是组合式 API&#xff1f; 组合式 API (Composition API) 是一系列 API 的集合&#xff0c;使我们可以使用函数而不是声明选项的方式书写 Vue 组件。它是一个概括性的术语&#xff0c;涵盖了以下方面的 API&#xff1a; 响应式 API&#xff1a;例如 ref() 和 reactive()&a…

TCP_IP(6)

网络层 在复杂的网络环境中确定一个合适的路径. IP协议 与TCP协议并列,都是网络体系中最核心的协议. 基本概念 主机:配有IP地址,但是不进行路由控制的设备; 路由器:即配有IP地址,又能进行路由控制; 节点:主机和路由器的统称; 协议头格式 4位版本号(version):指定IP协议的版…

python 人脸检测器

import cv2# 加载人脸检测器 关键文件 haarcascade_frontalface_default.xml face_cascade cv2.CascadeClassifier(haarcascade_frontalface_default.xml)# 读取图像 分析图片 ren4.png image cv2.imread(ren4.png) gray cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)# 进行人脸…

Unity类银河恶魔城学习记录7-5 p71 Improving sword throwing state源代码

Alex教程每一P的教程原代码加上我自己的理解初步理解写的注释&#xff0c;可供学习Alex教程的人参考 此代码仅为较上一P有所改变的代码 【Unity教程】从0编程制作类银河恶魔城游戏_哔哩哔哩_bilibili Sword_Skill.cs using System.Collections; using System.Collections.Ge…

基于Springboot+Vue实现的宿舍管理系统

基于SpringbootVue的宿舍管理系统 1.系统相关性介绍1.1 系统架构1.2 设计思路 2.功能模块介绍2.1 用户信息模块2.2 宿舍管理模块2.3 信息管理模块 3. 源码获取以及远程部署 前言&#xff1a; 在现代教育环境中&#xff0c;学生宿舍的管理显得尤为重要&#xff0c;需要一套能…