赞
踩
向量(Vectors)是新的 JSON。
这本身就是一个有趣的说法,因为向量是一种经过充分研究的数学结构,而JSON是一种数据交换格式。然而,在数据存储和检索领域,这两种数据表示形式都已成为其领域的通用语言,并且是现代应用程序开发中必不可少或即将成为必不可少的组成部分。如果目前的趋势继续下去(我认为他们会),向量将像JSON一样重要。
生成式人工智能及其相关热门话题促使开发人员寻求方便的方法来存储和运行针对这些系统输出的查询,而PostgreSQL由于许多原因而成为自然选择。但是,即使在生成式人工智能的炒作中,这并不是一种新的数据模式。向量作为数学概念已经存在数百年了。机器学习已经有了半个世纪的研究历程。数组作为向量的基本数据结构,在大多数计算机科学入门课程中都有教授。即使是PostgreSQL在20多年前就开始支持向量运算(稍后详细介绍)!
那么,有什么是新的呢?新的是AI/ML算法的可访问性,以及将某些“现实世界”结构(文本、图像、视频)表示为向量并在未来通过应用程序进行存储的简便性。虽然人们可能会指出将这些系统的输出(“嵌入”)存储在数据存储系统中并不是一件新的事情,但新出现的模式是几乎在任何应用程序中以接近实时的方式查询和返回这些数据的可访问性。
这与PostgreSQL有什么关系?一切!有效地存储和检索数据类型在常见模式中的使用,极大地简化了应用程序开发,允许人们将相关数据保存在同一位置,并可以与现有工具一起使用。我们在10年前就看到了这一点,当时是与JSON一起出现的,现在我们正在看到这一点与向量数据一起发生。
为了理解为什么向量是新的JSON,让我们回顾一下当JSON作为事实上的用于网络通信的数据类型时发生了什么。
在“JSON的崛起”期间,我还是一个应用程序开发者。我正在构建的系统要么向前端发出JSON数据以完成某种操作(例如,呈现可更新的小部件),要么与一个“现代”API一起工作,该API以JSON格式返回其数据。JSON的好处在于它的简单性(非常容易阅读和操作),同时又相对表达力较强,可以用作数据交换格式。我希望JSON能够具备一些特性,尤其是在数据库方面,我很喜欢有模式的概念,但JSON确实简化了系统之间的高效通信,无论是从开发还是运维的角度来看。
尽管JSON首先被设计为一种交换格式,人们会问:“我为什么不能原生地存储和查询它呢?”这就导致了专门的数据存储系统的出现,可以让您存储和查询JSON文档。虽然我尝试过几种用于解决特定问题的临时JSON存储系统,但出于性能和可维护性的原因,我不确定是否要将它们引入我的应用程序堆栈中(我不会具体提及名称,因为这个分析是在十多年前进行的,很多事情已经发生了改变)。这引出了一个问题 - 在PostgreSQL中是否可以存储JSON数据。
我记得我参加了PostgreSQL的活动,急切地等待着PostgreSQL对JSON文档的本地存储和检索支持的更新。我还记得PostgreSQL 9.2添加基于文本的JSON类型时的兴奋。PostgreSQL最初对JSON的支持验证了您存储的内容是有效的JSON,并附带了一些函数和操作符来帮助您提取文档中包含的数据。没有原生索引支持,但是如果您计划在文档中频繁查询某个键,则可以构建表达式索引。
PostgreSQL中最初的JSON支持帮助我解决了几个问题,尤其是,我的数据库中几个表的状态快照,以及记录我所使用的api的输出。最初的基于文本的JSON数据类型没有太多的搜索功能:可以构建表达式索引来查询JSON文档中的特定键,但实际上我会将该键存储在JSON文档旁边的列中。
这里有一个关键因素:最初对JSON的支持作为“JSON数据库”的效用有限。是的,我们现在可以存储JSON,我们有一些有限的查询能力,很明显,它需要更多的工作来与特殊JSON数据库的功能竞争。然而,PostgreSQL对于许多这样的用例来说仍然足够好,而且在某种程度上,开发人员可以接受这些限制,只要他们可以在现有的应用程序基础设施中使用基于文本的JSON数据类型。PostgreSQL也是第一个增加对JSON支持的关系数据库,它开创了一种趋势,最终导致在SQL标准中采用JSON。
然而,PostgreSQL作为“JSON数据库”的可行性随着PostgreSQL 9.4的发布而改变。这个版本增加了JSONB,这是JSON数据类型的二进制表示形式,但是提供了使用GIN索引搜索JSON文档中的任意数据的能力。从性能的角度来看,这使得PostgreSQL与JSON数据库不相上下,同时还提供了将数据保存在关系数据库中的所有其他好处。虽然花了几年的时间,PostgreSQL能够适应和发展,以支持应用程序的工作负载。
多年来,PostgreSQL对JSON的支持一直在不断发展和改进,毫无疑问,随着PostgreSQL继续实现和采用SQL/JSON,这种支持将继续下去。我曾与使用JSON支持的PostgreSQL用户交谈过,他们在PostgreSQL数据库中存储了数十tb的JSON文档——他们对这种体验有积极的反馈!
这个故事的关键部分是,开发人员愿意把赌注押在PostgreSQL上,让它成为一个有竞争力的JSON存储系统,并努力克服它最初的局限性,直到有了更强大的支持。这就引出了向量。
矢量并不新鲜,但最近它们的受欢迎程度激增。如前所述,这是由于AI/ML系统的新发现的可访问性,并且这些系统的输出是向量。一个常见的用例是在存储的数据(文本、声音、视频)上构建一个模型,将其转换为矢量格式,然后将其用于“语义搜索”。在这种情况下,当您接受新的输入,将其转换为相应的向量,并在数据库中找到最相似的结果时,将执行语义搜索。使用距离函数(如欧几里得或余弦距离)来发现相似性,并且结果通常以“k个最近邻”(k - nn)或k个最相似的对象为上限。对向量的“训练集”进行编码可能会花费很多时间,因此将它们“缓存”在永久数据存储系统(例如数据库)中并在那里执行K-NN查询是有意义的。拥有一组随时可以进行语义搜索的向量,通常会给用户带来更好的体验,这就产生了需要“向量数据库”的概念。
存储vector在PostgreSQL中并不新鲜。当PostgreSQL于1996年首次开源时,PostgreSQL数组类型就已经存在了(!),尽管多年来对其进行了许多改进。事实上,PostgreSQL的“数组”有点用词不当,因为它们可以存储多维数据(例如矩阵)。在PostgreSQL中,数组本身包含了有限的关于向量的操作功能,例如计算两个数组之间的“距离”。可以编写存储过程来处理这个问题,但这会给开发人员带来额外的工作。
幸运的是,多维数据集数据类型克服了这些限制。cube在PostgreSQL代码库中也已经存在了20多年,它是为在高维向量*上执行操作而设计的(稍后会详细介绍)。立方体包含了向量相似性搜索中使用的大多数常见距离函数,包括欧几里得距离,并且可以使用GiST索引来执行高效的K-NN查询!然而,cube只能存储100个维度的向量,而许多现代AI/ML系统的维度远远超过这个数字。
如果数组可以处理向量维数,但不能处理运算,而立方体可以处理运算,但不能处理维数,我们该怎么办?
PostgreSQL的基础之一是它的可扩展性:PostgreSQL提供了创建新数据类型和新索引方法的接口。这给了我们pgvector,一个开源的PostgreSQL扩展,它提供了一个可索引的向量数据类型。简而言之,pgvector允许您在PostgreSQL中存储向量,并使用各种距离度量执行K-NN查询:欧几里得,余弦和内积。截至今天,pgvector附带了一个索引,ivflat,它实现了vector索引的IVF FLAT方法。
当您查询索引向量数据时,所发生的情况可能与您在PostgreSQL中查询数据的方式略有不同。由于在高维向量上执行最近邻搜索的计算开销,许多向量索引方法寻找与正确答案“足够接近”的“近似”答案。这导致了“近似最近邻”(ANN)搜索领域的出现。人们查看人工神经网络查询的两个维度是性能和“召回率”之间的权衡,其中“召回率”是返回相关结果的百分比。
让我们以ivflat方法为例。在构建ivflflat索引时,您可以决定其中需要包含多少个列表。每个列表代表一个“中心”;这些中心使用k-means算法计算。一旦确定了所有的中心,ivflat将确定每个向量最接近的中心并将其添加到索引中。当需要查询矢量数据时,您可以决定要检查多少个中心,这是由ivflat决定的。探测器参数。这就是你看到人工神经网络性能/召回权衡的地方:你访问的中心越多,你的结果就越精确,但代价是性能。
由于将AI/ML的输出存储在“矢量数据库”和pgvector中很受欢迎,所以有很多关于如何使用pgvector的例子。因此,我将关注事情的发展方向。
与PostgreSQL 9.2天的JSON类似,我们在PostgreSQL中存储矢量数据的方式还处于早期阶段——虽然我们在PostgreSQL和pgvector中看到的很多东西都很好,但它将会变得更好。
pgvector已经可以处理AI/ML数据的许多常见用例——我已经看到许多用户成功地使用它部署应用程序!所以下一步是帮助它扩大规模。这与PostgreSQL中的JSON和JSONB没有太大的不同,但是将pgvector作为扩展将有助于更快地迭代。
在PostgreSQL内部开发者聚集的PGCon 2023会议上,我做了一个名为“vector are the new JSON”的闪电演讲,分享了用例和一些即将到来的挑战,以改进PostgreSQL和pgvector在查询矢量数据方面的性能。需要解决的一些问题(其中许多问题正在进行中!)包括向pgvector添加更多的并行性,为超过2000维的向量添加索引支持,以及在可能的情况下利用硬件加速来加快计算速度。好消息是,其中一些功能并不太难添加,它们只需要开源贡献!
使用PostgreSQL作为矢量数据库(强调数据库;-)是一件令人兴奋的事情,我希望,正如JSON的历史所显示的那样,PostgreSQL社区将找到一种可扩展且安全的方式来支持这种紧急工作负载。我鼓励你提供反馈——PostgreSQL本身和pgvector——关于你如何在PostgreSQL中处理矢量数据,或者你想如何在PostgreSQL中处理数据,因为这将有助于指导社区为矢量查询提供最佳支持。
标题:VECTORS ARE THE NEW JSON IN POSTGRESQL
作者:JONATHAN KATZ
链接:https://jkatz05.com/post/postgres/vectors-json-postgresql/
翻译:阎书利
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。