PostgreSQL中的向量是新的JSON

2023/08/30 16:29
阅读数 163

作者:乔纳森·卡茨(JONATHAN KATZ)
2023年6月26日

向量是新的 JSON。这本身就是一个有趣的陈述,因为向量是一种经过充分研究的数学结构,而JSON是一种数据交换格式。然而,在数据存储和检索领域,这两种数据表示形式都已成为其领域的通用语言,并且是现代应用程序开发中必不可少或即将成为必不可少的组成部分。如果目前的趋势继续下去(我认为他们会),向量将像JSON一样重要。


生成式人工智能(AI)和围绕它的所有讨论都促使开发人员寻找方便的方法来存储和运行针对这些系统输出的查询,PostgreSQL是一个很自然的选择,原因有很多。但即使围绕生成人工智能大肆宣传,这并不是一种新的数据模式。向量作为一个数学概念,已经存在了数百年。机器学习有超过半个世纪的研究价值。数组 - 向量的基本数据结构 - 在大多数入门计算机科学课程中教授。甚至 PostgreSQL 也支持向量操作超过 20 年(稍后会详细介绍)!


那么,什么是新的?这是这些AI / ML算法的可访问性,以及将一些“现实世界”结构(文本,图像,视频)表示为向量并将其存储以供应用程序将来使用是多么容易。再一次,虽然人们可能会指出,将这些系统的输出(“嵌入”)存储在数据存储系统中并不是什么新鲜事,但新兴模式是能够在几乎任何应用程序中近乎实时地查询和返回这些数据的可访问性。


这与PostgreSQL有什么关系?万事!高效存储和检索常见模式中使用的数据类型极大地简化了应用开发,让人们能够将其相关数据保存在同一个位置,并可以使用现有工具。我们在 10 多年前在 JSON 中看到了这一点,现在我们在向量数据中看到了这一点。


为了理解为什么向量是新的JSON,让我们回顾一下JSON成为Web通信事实上的数据类型时发生了什么。

PostgreSQL中JSON简史

早在“JSON的兴起”的时候,我还是一名应用程序开发人员。我正在构建的系统要么向前端发出JSON数据,以便它可以完成某种操作(例如,渲染可更新的小部件),要么使用以JSON格式返回数据的“现代”API。JSON的优点在于它的简单性(读取和操作都非常容易),而且作为一种数据交换格式,它具有相关的表达能力。在JSON中有一些我喜欢看到的东西——偏向于数据库端,我绝对是拥有模式的粉丝——但是JSON确实简化了系统之间的有效通信,从开发和操作的角度来看都是如此。


虽然JSON首先是一种交换格式,但人们确实问过:“为什么我不能在本地存储和查询它?这导致了专门的数据存储系统的出现,这些系统允许您存储和查询 JSON 文档。虽然我已经针对一个非常具体的问题尝试了几种不同的临时 JSON 存储系统,但由于性能和可维护性原因,我不确定是否要将它们引入我的应用程序堆栈(我不会指名道姓,因为我在十多年前就做了这个分析,并且很多事情都发生了变化)。这就引出了一个问题——是否可以将JSON数据存储在PostgreSQL中。


我记得去参加PostgreSQL活动时急切地等待PostgreSQL原生支持存储和检索JSON文档的更新。我记得PostgreSQL 9.2添加基于文本的JSON类型时的兴奋。PostgreSQL对 JSON 的初始支持验证了您存储的内容是有效的 JSON,并附带了一些函数和运算符,可帮助您提取文档中包含的数据。没有本机索引支持,但如果您计划频繁查询文档中的键,则可以生成表达式索引。


PostgreSQL中最初的JSON支持帮助我解决了几个问题,特别是,我的数据库中几个表的状态快照,以及记录我所使用的api的输出。最初的基于文本的JSON数据类型没有太多的搜索功能:可以构建表达式索引来查询JSON文档中的特定键,但实际上我会将该键存储在JSON文档相邻的列中。


这里有一个关键要素:最初对JSON的支持作为“JSON数据库”的效用有限。是的,我们现在可以存储 JSON,而且我们对它的查询能力有限,很明显它需要更多的工作来与临时 JSON 数据库的功能竞争。然而,PostgreSQL对于许多这些用例来说仍然足够好,并且部分开发人员可以接受这些限制,只要他们可以在现有的应用程序基础架构中使用基于文本的JSON数据类型。PostgreSQL也是第一个增加 的关系数据库,这一趋势最终导致在SQL标准中采用JSON。


然而,PostgreSQL作为“JSON数据库”的可行性随着PostgreSQL 9.4的发布而改变。此版本添加了 JSON 数据类型的二进制表示形式,但具有使用 GIN 索引搜索任意具有 JSON 文档数据的能力。从性能角度来看,这使得PostgreSQL与JSON数据库相提并论,同时仍然提供了将数据保存在关系数据库中的所有其他好处。虽然花了几年的时间,PostgreSQL能够适应和发展,以支持应用程序的工作负载。


多年来,PostgreSQL中对JSON的支持不断发展和改进,毫无疑问,随着PostgreSQL继续实现和采用SQL/JSON,这种支持将继续强化。我曾与PostgreSQL用户交谈过,他们在PostgreSQL数据库中使用JSON支持存储数十TB的JSON文档 - 他们对这种体验有积极的反馈!


这个故事的关键部分是开发人员愿意押注PostgreSQL拥有一个有竞争力的JSON存储系统,并利用其最初的限制,直到有更强大的支持。这就把我们带到了向量。

向量的兴起:“一种新型的JSON”

向量并不新鲜,但如今它们的受欢迎程度正在激增。如前所述,这是由于AI/ML系统的可访问性,并且这些系统的输出是向量。一个常见的用例是在存储的数据(文本、声音、视频)上构建模型,将其转换为向量格式,然后将其用于“语义搜索”。在这种情况下,当您采用新输入,将其转换为相应的向量并在数据库中查找最相似的结果时,将执行语义搜索。相似性是使用距离函数(例如欧几里得或余弦距离)发现的,结果通常限制在“k 最近邻”(K-NN) 或 k 个最相似的对象。对向量的“训练集”进行编码可能需要大量时间,因此将它们“缓存”在永久数据存储系统(例如数据库)中并在那里执行 K-NN 查询是有意义的。拥有一组准备好进行语义搜索的向量通常会为用户提供更好的体验,这引起了需要“向量数据库”的概念。


存储向量在PostgreSQL中并不是什么新鲜事。PostgreSQL数组类型在1996年首次开源时就已经存在了!尽管多年来对它进行了许多改进。事实上,PostgreSQL“数组”有点用词不当,因为它们可以存储多个维度的数据(例如矩阵)。在PostgreSQL数组中,原生包含围绕向量中常见的操作的有限功能,例如计算两个数组之间的“距离”。可以编写存储过程来处理此问题,但这会给开发人员带来额外的工作。


幸运的是,多维数据集(cube)数据类型克服了这些限制。在PostgreSQL代码库中也存在了20+年,并且旨在对更高维向量执行操作(稍后会详细介绍)。包含向量相似性搜索中使用的大多数常见距离函数,包括欧几里得距离,并且可以使用 GiST 索引执行高效的 K-NN 查询!然而,它被限制在存储 100 维的向量上,而许多现代 AI/ML 系统的维数远远超过这个维度。
那么,如果数组可以处理向量维数,但不能处理运算,而多维数据集(cube)可以处理运算,但不能处理维数,我们能做什么呢?

pgvector:一个开源扩展,用于在PostgreSQL中存储和搜索向量

PostgreSQL的基础之一是它的可扩展性:PostgreSQL具有创建新数据类型和新索引方法的接口。这给pgvector,一个开源的PostgreSQL扩展,提供了一个可索引的数据类型。简而言之,pgvector 允许您在 PostgreSQL 中存储向量,并使用各种距离指标执行 K-NN 查询:欧几里得、余弦和内积。截至今天,pgvector带有一个索引ivfflat,它实现了向量索引的IVF FLAT方法。


查询索引向量数据时发生的情况可能与您习惯于在 PostgreSQL 中查询数据的方式略有不同。由于对高维向量执行最近邻搜索的计算开销,许多向量索引方法会寻找与正确答案“足够接近”的“近似”答案。这导致了“近似最近邻”(ANN)搜索字段。人们在ANN查询中关注的两个维度是性能和“召回”之间的权衡,其中“召回”是返回的相关结果的百分比。


让我们以该方法为例。构建索引时,您可以决定要包含多少个索引。每个代表一个“中心”;这些中心是使用 k均值算法计算的。确定所有中心后, 确定每个向量最接近的中心并将其添加到索引中。当需要查询向量数据时,您可以决定要检查的中心数,这取决于参数。这就是您看到ANN性能/召回权衡的地方:您访问的中心越多,结果就越精确,但以牺牲性能为代价。
由于流行将AI/ML的输出存储在“向量数据库”中,并且有很多如何使用的例子。因此,我将专注于pgvector的发展方向。

在PostgreSQL中更好地支持向量的后续步骤

与 PostgreSQL 9.2 的 JSON 类似,我们正处于如何在 PostgreSQL 中存储向量数据的早期阶段——虽然我们在 PostgreSQL 和 pgvector 中看到的很多东西都非常好,但它会变得更好。
pgvector已经可以处理 AI/ML 数据的许多常见用例——我已经看到许多用户使用它成功部署应用程序!– 所以下一步是帮助它扩展。这与PostgreSQL中JSON和JSONB发生的事情没有太大区别,但是作为扩展将有助于pgvector更快地迭代。


在PGCon 2023上,这是一个PostgreSQL会议,许多内部开发人员聚集在一起,我发表了一个名为Vectors is the New JSON的闪电演讲,我分享了用例和一些即将到来的挑战,这些挑战是关于改进PostgreSQL查询向量数据的性能需要解决的一些问题(其中许多正在进行中!),涉及向pgvector添加更多的并行性,添加对超过2,000个维度的向量的索引支持,并在可能的情况下利用硬件加速来加快计算速度。好消息是,其中一些东西并不难添加,它们只需要开源贡献!


使用PostgreSQL作为向量数据库(强调数据库;-)有很多令人兴奋的事情,我希望,正如历史对JSON所表明的那样,PostgreSQL社区将找到一种方法来支持这种紧急工作负载,以一种可扩展和安全的方式。我鼓励你提供反馈 - 无论是关于PostgreSQL本身还是pgvector——关于你如何在PostgreSQL中使用向量数据,或者你想如何处理PostgreSQL中的数据,因为这将有助于指导社区为向量查询提供最佳支持。


本文分享自微信公众号 - 开源软件联盟PostgreSQL分会(kaiyuanlianmeng)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。

展开阅读全文
加载中
点击引领话题📣 发布并加入讨论🔥
0 评论
0 收藏
0
分享
返回顶部
顶部