Prisma 查询引擎,用 Rust 编写,一直是 Prisma ORM 的核心组成部分。它曾为未来而开发,但已不再与 Prisma ORM 当前的方向兼容。请继续阅读,了解我们从 Rust 到 TypeScript 的重写。
Prisma 正在做什么?!
在我们最近发布的 ORM 宣言中,我们描述了 Prisma ORM 在未来几个月和几年将如何管理。其中一个小细节是以下这段话:
我们正在通过将 Prisma 的核心逻辑从 Rust 迁移到 TypeScript 来解决这个问题,并重新设计 ORM,使其更易于定制和扩展。
这在我们之前的文章中只是一句话,但它引起了相当多的反响。
例如,我们非常喜欢 Theo 的这段视频:
总而言之,这些都是非常合理的反应。Rust 查询引擎从一开始就与 Prisma ORM 同在。我们在网上看到的讨论非常棒,但我们也想介入并提供一些更新,因为我们的 TypeScript 实现即将进入早期访问阶段。
简而言之,我们想让社区中的每个人都知道哪些正在改变,这些改变背后的动机,以及这些改变将如何实施。
Prisma 为什么选择 Rust?
在探讨 Prisma ORM 的未来之前,我们需要了解 Prisma ORM 为什么使用 Rust 引擎。当我们开始规划 Prisma 2(现在称为 Prisma ORM)时,我们有一个非常清晰的愿景:我们希望为尽可能多的语言构建 ORM——TypeScript、Go、Python、Scala、Rust 等。我们需要一个能够相对直接地添加新语言支持的解决方案。Rust 的性能优势和系统级方法使其成为这个核心查询引擎的自然选择。
这个决定也是对 GraphCool 和 Prisma 1 所做工作的延续。这些早期解决方案的核心、可部署基础设施演变为基于 Rust 的查询引擎——一个旨在处理生成 SQL 查询、管理连接池以及从数据库返回结果等繁重工作的二进制文件。这使得诸如 prisma-client-js
这样的特定语言客户端可以作为引擎上方的轻量级层。
为什么要放弃 Rust?
虽然强大的 Rust 引擎帮助我们快速提供了卓越的性能,但我们后来发现它带来了一些显著的挑战:
- 技能门槛: 对查询引擎的贡献需要 Rust 和 TypeScript 两种语言的熟练掌握,从而减少了社区参与的机会。
- 部署复杂性: 每个操作系统和 OpenSSL 库版本都需要自己的二进制文件,这使得部署变得复杂并减缓了开发速度。
- 兼容性问题: 现代 JavaScript 运行时、无服务器和边缘环境并非总是与大型 Rust 二进制文件兼容,这限制了 Prisma 的部署方式和地点。
此外,查询引擎的核心优势——支持多个客户端的能力——已不再是我们的重点。Prisma ORM 是一个 TypeScript 项目,虽然我们支持我们的社区客户端,但我们不会在内部开发它们。
考虑到这些因素,并加上我们致力于构建一个包容的、社区驱动的生态系统(如我们的ORM 宣言中所述),我们决定尽可能地将 Rust 查询引擎中的组件迁移到 TypeScript——简化贡献并减少部署麻烦,同时不牺牲 Prisma ORM 用户熟知和喜爱的开发体验。
重新定义查询执行
我们将在早期访问阶段引入的主要架构变更是将查询执行和数据库结果处理从 Rust 迁移到 TypeScript。
要理解这一变化,让我们回顾一下当前的查询引擎设置。
Prisma ORM 查询的当前执行方式
目前,您可以通过两种方式使用 Prisma ORM 查询数据库:
- 使用用 Rust 编写的数据库驱动。
- 使用用 TypeScript 编写的驱动适配器和驱动。
在第一种方法中,Prisma ORM 查询被传递给用 Rust 编写的查询引擎。这个引擎管理着从构建查询计划到执行查询并将结果返回给 JavaScript 客户端的一切。
然而,这种架构无法支持仅提供 JavaScript 驱动的数据库,例如 D1 和 Turso。为了解决这个限制,我们引入了驱动适配器。
当使用驱动适配器时,查询引擎仍然会开发查询计划并生成 SQL 语句。但是,执行通过驱动适配器委托给数据库。
这种方法实现了与 JavaScript 驱动的兼容性,但引入了一个权衡:数据必须从 JavaScript 序列化到 Rust,然后再回到 JavaScript,这降低了效率,并抵消了这种方法的一些优点。
Prisma ORM 查询的未来执行方式
在新的架构中,驱动适配器将继续使用。然而,Prisma ORM 将不再依赖基于 Rust 的查询引擎,而是将查询传递给 WASM 编译器,该编译器将返回查询计划。然后,此计划将完全在 TypeScript 中执行。
这种简化的架构带来了几项立竿见影的好处:
- 保留了对成熟 JavaScript 数据库驱动的支持。
- 减少了 JavaScript 和 Rust 之间数据转换的需要。
- 最小化了 Rust 和 JavaScript 之间传输的数据量。
- 消除了交付外部二进制文件的需求,因为查询编译器不再依赖于特定于系统的实用程序。
通过将查询执行转移到 TypeScript,我们简化了架构并增强了开发人员的兼容性和性能。
即将推出的简化体验
跨语言迁移逻辑是一个重大的转变,但我们正在逐步进行,以尽量减少中断。尽管这些变化是巨大的,但我们的首要任务是确保平稳过渡,同时保持您对 Prisma 期望的简洁性和可靠性。在这次迁移中,我们不仅解决了当前的挑战,还为增强的开发体验奠定了基础。
平稳过渡的步骤
我们的工程团队正在逐步将查询引擎逻辑过渡到代码库的 TypeScript 端。目前无法移动的组件正在被重新打包成一个 WASM 文件,并包含在 @prisma/client
npm 模块中。这个 WASM 文件充当查询编译器,简化了工作流程,而无需进行重大的 API 更改。
例如,我们计划取消对 binaryTargets
的要求,进一步简化开发体验。总的来说,Prisma ORM 的体验将保持熟悉和直观。
开启未来的机遇
这次转变不仅是为了解决当前的挑战,它还为创新创造了新的机会。事实上,查询编译器为我们的团队和社区探索了许多可能性。例如,参数化查询计划的使用可以允许保存查询计划以供重复使用,从而加快执行速度。另一个途径是在编译时构建初始查询计划,进一步减少运行时计算需求。
我们对这些可能性感到兴奋,并渴望听到您的想法!欢迎在我们的 GitHub 或 Discord 上加入讨论。
帮助我们构建更好的 Prisma ORM 体验
这个项目是使 Prisma ORM 对每个人都更好迈出的重要一步。Prisma ORM 的核心是为像您这样的开发者构建的。您的反馈和协作对这段旅程至关重要。
以下是您可以提供帮助的方式:
- 提交问题以报告错误或提出功能建议。
- 使用讨论区分享您的想法。
- 加入我们的 Discord 参与社区活动和开发者 AMA。
最后,测试我们的早期访问客户端!我们将在 GitHub 和 Discord 上分享更新。
这是 Prisma 激动人心的时刻,未来还有更多的改进和机遇。感谢您激励我们成长并成为这段旅程的一部分。
想成为第一批尝试我们新的早期访问客户端的用户吗?在 X 上关注我们,并加入我们的 Discord 以获取最新动态。
不要错过下一篇文章!
订阅 Prisma 新闻通讯