
上文聊完Embedding模型将文本内容转换为了向量并了解两个向量之间如何判断相似度是正相关还是负相关。但是我们的chunk如果有几百万个我们这时候来一个语句通过embedding生成向量后怎么跟几百万个向量匹配呢正常数据库该怎么做假设我们使用正常的mysql拿一个text字段去存储chunk对应的向量。那我们进行匹配的时候因为不是精确匹配也无法模糊匹配不可能在数据库层进行匹配出来的所以我们只能将向量的数据在数据库中查询出来然后在内存中进行匹配最简单粗暴的办法。但是得考虑到数据量太大每次读取数据都会走磁盘io的操作以及未来并发一大很容易就会将数据库打崩。所以我们如果要在生产环境上使用的话尽量不用这种方式。核心索引算法在具体介绍向量数据库前先介绍下向量索引的核心算法。因为我们在之前的文章里也讲过可以使用余弦相似度的方式计算两个向量之间的相似度。但是我们应该如何从百万个向量里找到最匹配我们目标向量的向量呢大概有以下几种方式。暴力法最简单粗暴的办法就是一个个匹配弄个循环每个都去算一下和目标向量的匹配度然后统计所有匹配度里最高的n个向量。优点是极致的简单代码量小缺点是效率堪忧需要对几百万个向量进行余弦相似度的计算。那有没有可以不用全局搜而是只比较其中一部分向量就找到大概率最相似的向量呢有的这就是 ANNApproximate Nearest Neighbor近似最近邻搜索的核心思想。比如以下几种索引算法。IVF倒排文件索引INV的宗旨是先分区再搜索。怎么个理解呢可以想象把所有的向量都平摊在一个数学坐标内也就是一张图里通常先使用K-Means等算法将所有向量聚类成多个“单元”(cell)搜索时先找到距离目标向量最近的几个中心点即最可能的几个簇然后只在这些簇内进行精确计算。最后得到最高匹配度的top-n个向量。优点是一次可以过滤掉90%的向量只处理最终10%的向量缺点是数据如果分布不均匀效果可能一般以及还是需要处理剩下的10%HNSW分层可导航小世界图这是最主流的索引算法它的实现有点像redis的zset跳表的形式跳表的特色就是有多层节点下层节点最多上层节点最少然后从上到下一层一层寻找最匹配的节点直到找到符合目标的节点返回。HNSW也是差不多的原理可以看作是多层图最上层拥有最少的向量第二层向量变多最底层有所有的向量当目标向量进行匹配时先在第一层匹配最相似的向量匹配后从第二层找到周围最匹配的向量直到最后一层找到最相似的向量为止。相对于其他的索引算法这种算法的效率已经算做很高了。优点就是搜索的效率最高。缺点就是多层的向量很占用内存。HNSW通常适用于百万到千万级的数据量这主要受限于内存容量。对于亿级甚至更大规模的数据需要将索引存储在磁盘上以容纳数据此时可采用像DiskANN这样的算法但通常会以牺牲部分搜索速度为代价主流向量数据库有些专门为向量检索而设计的数据库比如Milvus、Pinecone、Chroma等。Milvus适用的向量数据量在百万到十亿级别之间支持多种索引算法比如HNSW、DISKANN等并且是开源的支持java的技术栈提供官方的Java SDK、丰富的Java示例。其中索引算法的选择可以按上述说的根据数据量来决定具体适用什么索引算法。