百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术分析 > 正文

PostgreSQL 与 MongoDB:哪个更适合 GenAI?

liebian365 2024-11-05 11:45 19 浏览 0 评论

导读:找出哪种数据模型(RDBMS 或文档)更适合大型、复杂与生成式 AI 的工作负载。

各位朋友,生成式人工智能 (GenAI) 应用程序使用数据的方式与传统的在线事务处理 (OLTP) 工作负载是不一样的。

后者以小块的形式处理数据,通常以行和表的形式,并且数据结构相对简单。大语言模型 (LLM)训练需要更丰富的文档结构或二进制对象,其大小可能为几千字节甚至几兆字节。

检索增强生成 (RAG)是一种广泛应用于 GenAI 应用程序的数据检索技术,它利用复杂的数据结构来构建提示语并实时生成响应。

此外,与任何其他类型的现代工作负载相比,人工智能驱动的工作负载更需要底层数据库系统能够快速高效地处理针对此类数据的查询。

传统关系数据库管理系统 (RDBMS)数据库平台未针对此类工作负载进行过设计。它们所基于的存储引擎在行大小方面假设存在一致性,并且它们在使用具有类型属性的记录行时运行效率最高。

使用 RDBMS 的最佳实践包括最小化表中的属性数量、使用垂直分区以及保持行数较小以及避免行外存储。这也适用于在 RDBMS 中使用JSON属性类型,这允许开发者使用可在复杂查询中引用的灵活架构对象来扩展其关系表的行。

为了让它们保持相关性,一种新的基于文档和对象的 NoSQL 替代方案已经发展起来,更能够满足这一需求。

在开源 RDBMS PostgreSQL中,标准实践指导是尽量减少值中包含 JSON 或 JSONB 属性的数量,也可以使用稀疏填充对象。

除了数据模型的差异之外,对于 GenAI 的工作负载而言, MongoDB等文档数据库相对于 PostgreSQL 等 RDBMS 平台的最大优势之一在于底层设计。

MongoDB 建立在存储引擎之上,该引擎旨在处理大小各异(从几个字节到几兆字节)丰富且复杂的文档。

当今 OLTP 工作负载越来越频繁地让小型、一致性设计的 RDBMS 平台对大型数据对象采用行外存储。但是行外存储技术(如 PostgreSQL 的TOAST)可能会带来性能瓶颈,因为查询无法再从表的行中访问所需的数据,从而导致从大型对象存储层进行二次检索。

另外,MongoDB 利用一个称为 BSON 的二进制文档结构来存储和传输强类型属性数据,这些数据由服务器处理,并以相同的格式存储在磁盘上,从而无需到服务器端解析。

RDBMS 数据库(例如 PostgreSQL)将复杂的 JSON 传输为文本格式。这要求服务器端解析写入内容,至少验证 JSON 格式或(在 JSONB 反序列化的情况下)属性值,以便它们可以在需要计算值的服务器端查询中有效使用。

在输出过程中,数据必须先序列化为 JSON 文本,然后才能传输到客户端。

我们将在下面的基准测试中,展示这一对大型文档的开销,虽然巨大但是可衡量的过程。

MongoDB 与 PostgreSQL 的比较

随着数据库需要存储和处理的对象的平均大小急剧增加, Gen AI 给系统带来了新的挑战。为了评估 PostgreSQL JSON/JSONB 与 MongoDB BSON 的性能,我们在同一硬件上运行了两台服务器,分别为:

Windows 10 Pro 32GB RAM Intel Core i7-8700K CPU@3.70GHz

PostgreSQL v16.2 MongoDB v7.0.8

我们开始测量单线程性能,以便更好地了解客户端和服务器之间的协议开销。

如前所述,MongoDB 专门使用 BSON 来减少这种开销,即无需序列化和反序列化数据。线程化或运行多个客户端会掩盖这种开销,而无需测量整个系统的整体资源利用率。

对于写入工作负载,我们将 10,000 个文档插入到单个表或集合中,具有以下配置和有效负载大小:

  • 具有 10、200、1000、2000 和 4000 字节有效载荷的单一属性。
  • 多属性,具有 10 个 1 字节、50 个 4 字节、100 个 10 字节、100 个 20 字节和 100 个 40 字节属性。

其中,PostgreSQL 服务器使用以下参数进行配置:

  • 所有表均创建为0记录表。
  • 设置shared_buffers=8GB。
  • 设置synchronous_commit=off。
  • 设置 wal_buffers=48MB。

MongoDB 服务器是默认安装,未应用任何调整。

我们进行的第一个测试是插入 10,000 个单属性文档,同时测量有效负载从 10B 增加到 ~4KB 时完成所需的总时间(以毫秒为单位)。

下图显示了原始数据与结果图表。


10K 记录插入(单一属性有效载荷)


MongoDB

Postgres(JSONB)

Postgres(JSON)

n=1,s=10

773

399

331

n=1,s=200

789

2184

969

n=1,s=1000

750

8393

4071

n=1,s=2000

850

16387

7944

n=1,s=4000

829

31705

15767

当涉及大型文档时,数据非常清楚:PostgreSQL 的性能与 MongoDB 相当,直到文档大小开始增长到几百字节以上,一旦 TOAST 在 2KB 左右启动,情况就会变得“糟糕”。

另一方面,毫不奇怪,PostgreSQL 在处理其设计用于处理的工作负载类型(处理小块数据)方面相当有竞争力。然而,随着有效负载的大小增加,处理开销很快就会变得明显。PostgreSQL 仅验证 JSON 属性的格式,而 JSONB 还会解析属性值。

在本测试中可以看到 JSONB 产生的额外开销。MongoDB BSON 在所有有效负载上的表现都远远优于 JSON 和 JSONB,并且曲线非常平坦。

测试更多属性和更大的有效载荷

下一个测试是插入 10,000 个多属性文档,同时测量完成测试所需的总时间(以毫秒为单位),因为有效负载分布在多个属性中,大小从 10B 增加到 ~4KB。

下图显示了原始数据和结果图表。


10K 物品插入(多属性有效载荷)


MongoDB

Postgres(JSONB)

Postgres(JSON)

n=10,s=10

531

415

322

n=10,s=200

569

2040

793

n=50,s=1000

641

9504

4419

n=100,s=2000

812

19213

9181

n=200,s=4000

1085

37278

17460

主要之结论为,随着属性数量的增加,JSONB 的解析开销会更高。

MongoDB BSON 和 PostgreSQL JSON 在单属性和多属性测试中都保持了相对平稳的性能。

BSON 没有任何解析开销,而 JSON 只是验证格式,因此在插入复杂文档时,两者都不需要做太多工作。MongoDB BSON 仍然是明显的赢家,而 JSONB 则要落后很多。

MongoDB 与 PostgreSQL 读取测试

最后一个测试是针对多属性文档集的读取。

索引是在包含 10 个整数值的数组属性上创建的,这些整数值是从上一次基准测试期间插入的 10,000 个文档 ID 中随机选择的。

在 PostgreSQL 中,属性是在行本身上创建的,而不是在JSON/JSONB 文档中创建。这样做是为了消除与索引文档属性相关的任何可能的开销,然而 PostgreSQL 最初并不是为此设计的。没有理由不在实际工作负载中将索引属性投射到行中,因此以这种方式配置测试代表了更平等的比较。

查询测试包括遍历 10,000 个唯一整数 ID 值,并针对每个值选择表或集合中索引数组中包含该 ID 的所有文档。结果查询测试中共检索了大约 100,000 个文档。

在这两种情况下,都会迭代整个结果集,但不会处理实际数据。这导致基准测试结果偏向了 PostgreSQL,因为 JSON 文本实际上不会被客户端解析为可用对象,而 BSON 文档则不需要解析。

尽管PostgreSQL有这样的特色,但结果还是有力地证明了 MongoDB 的优势。


数组索引查询测试


MongoDB

Postgres(JSONB)

Postgres(JSON)

n=10,s=10

3587

19933

18749

n=10,s=200

3810

23619

23946

n=50,s=1000

4741

27760

21311

n=100,s=2000

6023

36701

23264

n=200,s=4000

8352

53808

27789


我们看到,JSON 和 JSONB 的序列化相关开销都很高。MongoDB 显然受益于 BSON 不需要序列化的事实。对于 PostgreSQL,没有测量与 JSON 文本反序列化相关的开销,因为文本在代码中会被丢弃。

即使文档较小,MongoDB 也以较大地优势胜出。一个有趣的结论是 JSONB 也会在读取时产生影响,因为类型化属性值的序列化似乎会产生更多成本。

相比之下,尽管 JSONB 的读取速度更快,但如果文档中存储的数据值实际上并未在查询或处理的服务器端引用,那么最好使用 JSON。

结语

考虑到 RDBMS 在宽行和大数据属性方面的性能限制,这些测试表明,像 PostgreSQL 这样的系统将难以处理生成式 AI 工作负载所需的多样、复杂的文档数据。

而使用文档型数据库来处理这些文档数据,可以获得更好的性能。

参考:

https://db-engines.com/en/system/Cassandra%3BMongoDB%3BPostgreSQL

https://airbyte.com/data-engineering-resources/mongodb-vs-postgresql

相关推荐

go语言也可以做gui,go-fltk让你做出c++级别的桌面应用

大家都知道go语言生态并没有什么好的gui开发框架,“能用”的一个手就能数的清,好用的就更是少之又少。今天为大家推荐一个go的gui库go-fltk。它是通过cgo调用了c++的fltk库,性能非常高...

旧电脑的首选系统:TinyCore!体积小+精简+速度极快,你敢安装吗

这几天老毛桃整理了几个微型Linux发行版,准备分享给大家。要知道可供我们日常使用的Linux发行版有很多,但其中的一些发行版经常会被大家忽视。其实这些微型Linux发行版是一种非常强大的创新:在一台...

codeblocks和VS2019下的fltk使用中文

在fltk中用中文有点问题。英文是这样。中文就成这个样子了。我查了查资料,说用UTF-8编码就行了。edit->Fileencoding->UTF-8然后保存文件。看下下边的编码指示确...

FLTK(Fast Light Toolkit)一个轻量级的跨平台Python GUI库

FLTK(FastLightToolkit)是一个轻量级的跨平台GUI库,特别适用于开发需要快速、高效且简单界面的应用程序。本文将介绍Python中的FLTK库,包括其特性、应用场景以及如何通过代...

中科院开源 RISC-V 处理器“香山”流片,已成功运行 Linux

IT之家1月29日消息,去年6月份,中科院大学教授、中科院计算所研究员包云岗,发布了开源高性能RISC-V处理器核心——香山。近日,包云岗在社交平台晒出图片,香山芯片已流片,回片后...

Linux 5.13内核有望合并对苹果M1处理器支持的初步代码

预计Linux5.13将初步支持苹果SiliconM1处理器,不过完整的支持工作可能还需要几年时间才能完全完成。虽然Linux已经可以在苹果SiliconM1上运行,但这需要通过一系列的补丁才能...

Ubuntu系统下COM口测试教程(ubuntu port)

1、在待测试的板上下载minicom,下载minicom有两种方法:方法一:在Ubuntu软件中心里面搜索下载方法二:按“Ctrl+Alt+T”打开终端,打开终端后输入“sudosu”回车;在下...

湖北嵌入式软件工程师培训怎么选,让自己脱颖而出

很多年轻人毕业即失业、面试总是不如意、薪酬不满意、在家躺平。“就业难”该如何应对,参加培训是否能改变自己的职业走向,在湖北,有哪些嵌入式软件工程师培训怎么选值得推荐?粤嵌科技在嵌入式培训领域有十几年经...

新阁上位机开发---10年工程师的Modbus总结

前言我算了一下,今年是我跟Modbus相识的第10年,从最开始的简单应用到协议了解,从协议开发到协议讲解,这个陪伴了10年的协议,它一直没变,变的只是我对它的理解和认识。我一直认为Modbus协议的存...

创建你的第一个可运行的嵌入式Linux系统-5

@ZHangZMo在MicrochipBuildroot中配置QT5选择Graphic配置文件增加QT5的配置修改根文件系统支持QT5修改output/target/etc/profile配置文件...

如何在Linux下给zigbee CC2530实现上位机

0、前言网友提问如下:粉丝提问项目框架汇总下这个网友的问题,其实就是实现一个网关程序,内容分为几块:下位机,通过串口与上位机相连;下位机要能够接收上位机下发的命令,并解析这些命令;下位机能够根据这些命...

Python实现串口助手 - 03串口功能实现

 串口调试助手是最核心的当然是串口数据收发与显示的功能,pzh-py-com借助的是pySerial库实现串口收发功能,今天痞子衡为大家介绍pySerial是如何在pzh-py-com发挥功能的。一、...

为什么选择UART(串口)作为调试接口,而不是I2C、SPI等其他接口

UART(通用异步收发传输器)通常被选作调试接口有以下几个原因:简单性:协议简单:UART的协议非常简单,只需设置波特率、数据位、停止位和校验位就可以进行通信。相比之下,I2C和SPI需要处理更多的通...

同一个类,不同代码,Qt 串口类QSerialPort 与各种外设通讯处理

串口通讯在各种外设通讯中是常见接口,因为各种嵌入式CPU中串口标配,工业控制中如果不够还通过各种串口芯片进行扩展。比如spi接口的W25Q128FV.对于软件而言,因为驱动接口固定,软件也相对好写,因...

嵌入式linux为什么可以通过PC上的串口去执行命令?

1、uboot(负责初始化基本硬bai件,如串口,网卡,usb口等,然du后引导系统zhi运行)2、linux系统(真正的操作系统)3、你的应用程序(基于操作系统的软件应用)当你开发板上电时,u...

取消回复欢迎 发表评论: