关系型数据库
在了解什么是向量数据库之前,必须先对常见的关系型数据库进行分析。
关系型数据库,是指采用了关系模型来组织数据的数据库,其以行和列的形式存储数据,以便于用户理解,关系型数据库这一系列的行和列被称为表,一组表组成了数据库。
-
同一组的实体具有相同的数据结构
-
实体通过主键(ID)组织数据结构 (使用 树 进行存储)
-
实体数据结构中的大部分属性都是可以参与比较的
-
至于那些不可以参与比较的属性,无法被检索
- 例如,数据只是编码,不能反映实体的关系,例如"太阳"、"月亮"、"星星" 编码上的比较不能反映
举例,我们可以将图片(转为二进制)存放到关系型数据库,但是我们没有办法直接以图搜图
字符串(自然语言文本)基本上也可以认为是无法比较的,因为大部分的操作都是十分昂贵的
向量化
向量可以进行比较,如果将那些不可以比较的数据转换成为向量,且这些向量的分布和距离可以反映出实体的关系,那么就可以通过比较向量的关键进行检索,也就可以实现图搜图、文搜文的功能了
巧了,通过深度学习的模型,就可以实现向量化(或者应该称为vector embeddings)。例如可以将不同尺寸、不同内容的图片映射成为同一个空间内的向量,或者将不同长度的文本映射到同一个向量空间内,在同一个空间中,相邻的向量具有相近的语义含义。(实际上向量数据库正是为了辅助深度学习而生的)
虽然向量化是基础,但是向量化一般是专门的模型去实现,而不是数据库负责。(因为模型和业务强相关,且会定期更新)
但是需要数据库负责向量的存储、更新&版本管理
向量相似度检索(vector similarity search)
相对于传统的标量数据库
最近邻搜索,或简称 ANN 搜索,由于提出的解决方案数量之多,因此可以将其单独视为机器学习和模式识别的一个子领域。
向量的存储与索引(Vector Index)
- 向量很长(高维数据) (矢量压缩技术)
- 向量空间极其稀疏
- 向量间需要大量计算距离,需要计算不同的距离
第一种 Hashing-based
它的思路很简单,找到一组哈希函数,哈希高维空间里的一些点,那个值依然能表示出它的近邻关系,用这个哈希函数把这个空间分成很多份,在查询的时候,根据要查的数据先做一个哈希,找到对应的桶里面去,计算量就可以大大减少。
第二种 Tree partitioning based
它基于解释空间划分的一个思想,按照不同的纬度把空间进行多次划分,最终做成一个树结构。
第三种 IVF
它本质上就是做一个聚类,然后在这个聚类当中找到每个聚类中间点,查询的时候去跟这些中间点做比较,距离比较近的就认为可能有最近邻的数据,只去搜索其中的一部分数据。
第四种 Graph based index
它的实现方式是构建近邻图,在高维空间下构建这张图的时候,通过一种算法去找到一些最近邻,在查询的过程中,从图上任意一个点出发,不停地通过最近邻找到最近的节点,发现周围没有更优解了,它就是局部最优,如果扩散的节点数足够多,最终召回率相对比较高。这种图结构索引相对执行速度比较快,但占有内存相对会大一些。
前两种做法它都存在一个比较大的问题,就是召回精度不够,随着纬度变大,召回精度可能会变得越来越低,现在在工业中主要是采用的后两种做法。
开源的向量数据库
Faiss
- Facebook 开源的
- 一个 C++ library
- vector indices
Milvus
- 基于 Faiss 开发
- 引擎层用 C++ 写的
Qdrant
- 基于 Rust 的向量数据库
总结
将上述提到的基本概念进行总结,个人认为,向量数据库有3个关键
-
向量化(编码)
- 不同于字符串文本编码或者图片的编码,向量化的模型可能会不断更新,这就对向量数据库提出了更新和版本管理的需求
- 向量化的质量,决定了向量数据库效果的上限
- 向量化过程无法通用,至少目前没有办法,是和业务强相关的
-
数据结构
- 合理地构建数据结构管理向量,并保证计算和检索时候的性能
- 这个点决定了向量数据库的性能,即决定了向量数据库效果的下限
-
距离计算
- 如何更合理的计算向量间的距离,同时尽量减少资源的占用