我们创建了开源性能基准测试,用于比较 Prisma ORM、TypeORM 和 Drizzle ORM 在不同数据库提供商(如 AWS RDS 上的 PostgreSQL、Supabase 和 Neon)上的查询延迟。请继续阅读,了解我们的方法论以及哪个 TypeScript ORM 最快。

目录
太长不看
为您的应用程序选择最佳 ORM 需要考虑多个因素,其中查询性能是一个重要因素。
为了帮助您决定为 TypeScript 应用程序使用哪个 ORM,我们创建了开源性能基准测试,比较了三个 ORM 库的查询性能:Prisma ORM、TypeORM 和 Drizzle ORM(使用它们的查询 API)。
查看基准测试结果
那么,哪个 ORM 最快呢?(可能令人不满意)的答案是:这取决于具体情况!
根据我们收集的数据,无法得出结论说某个 ORM 总是比其他 ORM 表现更好。相反,这取决于具体的查询、数据集、模式以及查询执行的基础设施。
请查看下面的性能清单,以确保您的 Prisma ORM 查询达到最佳性能。
我们的基准测试方法
测量和比较查询性能可能是一项艰巨的任务,要创建一个公平的比较,需要考虑很多因素。
通过我们的基准测试,我们希望在确保基准测试公平且有意义以帮助人们就下一个项目使用哪个 ORM 做出明智决策,以及保持简单易懂而不过多地引入间接层或数据处理之间取得平衡。
您可以在此处找到我们用于测量查询性能的应用程序。
设置
我们为 Prisma ORM、TypeORM 和 Drizzle ORM 创建了 14 个等效查询。这些查询是针对一个包含 4 个 Prisma 模型(5 个表,因为有一个隐式多对多关系在底层使用了额外的关系表)的模式发送的。
每个查询的延迟通过使用此函数中的performance.now()
进行测量
例如,Prisma ORM 的普通findMany
查询可以这样测量
每个 ORM 每个数据库都有一个脚本(例如prisma-postgres.ts
),它单独测量所有 14 个查询的延迟并将结果存储在.csv
文件中。
这些脚本已在 EC2 实例上针对各种提供商托管的 PostgreSQL 数据库执行
每个脚本开始时建立数据库连接,结束时关闭。
数据准备
示例数据使用faker.js进行填充。为了以确定性的方式重新创建相同的示例数据集,我们向faker
实例提供了seed
值。
数据集的大小在运行基准测试时可配置。它决定了每个表创建的记录数量。例如,如果创建大小为1000
的数据集,则Customer
、Product
和Address
表中将有 1000 条记录,而Order
表中将有 10000 条记录(Order
表因其与Product
的多对多关系而乘以10
倍,使数据集更真实)。
基准测试执行
要执行基准测试,您可以按如下方式调用脚本
这将对每个表 1000 条记录的数据集执行预定义查询 500 次。数据库 URL 也可以作为环境变量提供。
为了收集数据,我们在生产基础设施上执行了基准测试,以模拟实际使用场景。脚本已在具有此规格的 EC2 实例上执行
我们使用的数据库具有以下规格
发布基准测试结果
我们已经将执行的基准测试结果发布在:https://benchmarks.prisma.io。
该表显示了我们执行的 500 次迭代中查询延迟的中位数。请注意,我们通过删除高于第 99 百分位数 (p99) 的值来剔除 500 次迭代中的异常值。
表格的列代表三个 ORM 库,行显示了已进行基准测试的查询。
展开单元格时,您可以查看有关查询的一些详细信息,例如
- 生成结果的实际代码片段及其查询。
- 一个直方图,用于可视化收集数据的分布。在这些图表中,左侧的条形越高越好,因为它表明更多的迭代具有更低的延迟。
注意事项
基准测试本身就是一个棘手的话题,很难做到完美。当公司发布性能基准测试时,它们通常会显示其产品在市场上是最快的,同时又让其他人难以重现结果,并掩盖从原始数据收集到结果呈现的路径。
我们尽力创建了一个公平中立的设置,它易于理解并能产生有意义的结果。即便如此,在查看基准测试结果时,仍需考虑以下几点注意事项
- TypeORM 和 Drizzle ORM 的 API 更受限制,一些 Prisma ORM 查询(如嵌套创建)无法通过其高级抽象表达。在这种情况下,我们不得不回退到使用它们的 SQL 查询构建器。
- 由于网络延迟,结果在不同迭代之间存在预期差异。为了减少这种影响,我们执行了 500 次基准测试,并在发布的基准测试结果中显示了中位数和直方图。
- 我们进一步确保执行查询的机器与访问的数据库位于同一区域,以将网络延迟降至最低。
- 在我们的基准测试中,我们没有采取任何措施来减少数据库级别或操作系统级别缓存的影响。
- 所有基准测试迭代都使用相应 ORM / 驱动程序库的默认连接池大小。
- 虽然我们努力使基准测试设置尽可能真实,但我们不得不在模式和查询上做出一些权衡。例如,我们没有向模式添加特殊索引,有时故意使用过于简单的查询,以便能够正确比较每个 ORM 的高级 API。
我们投入了大量精力使您可以轻松自行运行基准测试,所以请尝试一下,如果您想贡献改进,请随时联系我们!
哪个 ORM 最快?
虽然可能令人不满意,但答案常常是:这取决于具体情况。性能是一个复杂而细致的话题,它取决于各种因素,并且众所周知难以预测。
请参阅下面的性能清单,以确保您的查询达到最佳速度。
虽然无法对这个问题给出确切的答案,但我们可以尝试寻找一些模式并进行分析。
不同数据库提供商之间的低差异
首先,我们发现不同数据库提供商之间的差异通常可以忽略不计。例如,仅查看普通的findMany
查询,我们可以从中位数和直方图分布中看到,性能的差异很小
大概 RDS 具有优势,因为基准测试脚本是在同一安全组内的 EC2 实例上执行的,而 Supabase 和 Neon 数据库则可通过公共互联网访问。
更多信息,请务必访问基准测试网站以检查我们的结果,或使用您选择的数据库提供商自行运行基准测试。
大多数查询性能相似
如果您放大并远距离观察结果,您会发现大多数查询的性能实际上相差无几,只有几毫秒的差异。例如,以下是我们从 AWS RDS 收集到的结果
用户体验研究表明,低于 100 毫秒的延迟用户是察觉不到的,并且仍然会让系统感觉即时响应。因此,在大多数情况下,这些微小差异可能不应该是您为下一个项目选择 ORM 的主要因素。
当然,数据库查询延迟只是您正在构建的应用程序整体性能中的一个因素,因此请务必测量和优化其他方面,特别是系统中的所有网络边界(例如 HTTP 层)。
主要的异常值:嵌套查找所有
嵌套查找所有查询在所有 ORM 和所有数据库提供商中都特别慢。这是一个简单的查询,看起来像这样
Prisma ORM
Drizzle ORM
TypeORM
以 RDS 为例,这是我们收集的结果中的中位数
此查询对所有 ORM 来说都比其他查询慢得多,因为它从两个不同的表中获取数据,并且返回的数据量非常可观。
结论
我们收集的数据无法对每个 ORM 的个体性能得出确切结论。关于查询性能的残酷事实是,使用每个 ORM 库都可以编写快速查询,也可以编写慢速查询。
最终,应用程序的大部分性能取决于开发人员遵循最佳实践(请参阅下面的性能清单)、识别慢速查询并随着时间推移对其进行优化的能力。
提升 Prisma ORM 查询性能
性能对我们 Prisma 至关重要,我们最近大量关注于改进 Prisma ORM 在这方面的各个方面,例如通过引入使用数据库级别 JOIN的选项,在v5
中实现多项性能改进,将无服务器冷启动时间缩短 9 倍,或者在最新5.17.0
版本中将$queryRaw
的速度提高 2 倍。
Prisma ORM 性能清单
以下是一个基本清单,可帮助您确保 Prisma ORM 查询达到最佳性能
- 将服务器和数据库托管在同一区域。
- 为您查询中频繁使用的列添加索引。
- 确保生产环境中至少有 3 个 CPU 核心可用。
- 在需要时测量性能并使用原始 SQL 优化查询。
- 使用 Prisma ORM 的OpenTelemetry 跟踪和指标功能监控您的查询。
- 为您的数据库添加缓存层(例如Prisma Accelerate)。
- 如果您的应用程序是无服务器的,请遵循无服务器性能的最佳实践。
如果您遵循了这些建议,但仍然看到慢速查询,请在GitHub 上开一个 issue,并提供您的查询详细信息,以便我们确保它达到应有的速度!
Prisma Optimize 提供的洞察和建议
为了支持您测量性能并加快 Prisma ORM 查询速度,我们最近推出了Prisma Optimize。
Optimize 捕获通过 Prisma ORM 发送到数据库的所有查询,并通过详细的跟踪信息为您提供其性能洞察。未来,Optimize 将能够为您提供加快慢速查询的建议,例如,当返回的行数过多或应在模式中定义索引时给出建议。
查看基准测试结果
您可以在https://benchmarks.prisma.io上找到我们的基准测试结果。查看它们,并在X和Discord上告诉我们您的想法。我们特别期待听到您认为如何能使这个基准测试对您更有帮助,并欢迎改进建议!
不要错过下一篇文章!
订阅 Prisma 通讯