使用大型 Prisma schema 优化 TypeScript 性能
在 Prisma 应用程序中使用大型数据库模式时,类型定义策略的一个简单更改可以带来巨大的性能改进。
| 方法 | 类型 | 实例化 | 内存 | 编译时间 |
|---|---|---|---|---|
| 直接引用 | 269,597 | 2,772,929 | 395MB | 1.86s |
| typeof 技术 | 222 (减少 99.9%) | 152 (减少 99.9%) | 147MB (减少 62%) | 0.41s (减少 78%) |
(性能已使用 tsc --noEmit --extendedDiagnostics 进行验证。)
本指南将向您展示如何使用 TypeScript 的 typeof 运算符而不是直接类型引用来实现这些显著的性能提升。
测试模式概述
性能测量是使用一个有意复杂的 Prisma 模式进行的,该模式包含 30 个相互关联的模型,创建了深层关系链。
// Example of the test schema structure
model Tree1 {
id Int @id @default(autoincrement())
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
published Boolean @default(false)
title String
childId Int
Tree2 Tree2[]
}
model Tree2 {
id Int @id @default(autoincrement())
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
published Boolean @default(false)
title String
childTree Tree1 @relation(fields: [childId], references: [id])
childId Int
Tree3 Tree3? @relation(fields: [tree3Id], references: [id])
tree3Id Int?
}
// ... continues through Tree30 with similar interconnected patterns
此模式创建了复杂的类型依赖关系,对 TypeScript 编译进行压力测试,模拟具有广泛表关系的企业级实际应用程序。
问题
在具有大量数据库模式的企业级应用程序中——想想拥有数百种产品变体的电子商务平台、具有复杂交易层次结构的金融系统或具有复杂关系网络的內容管理系统——Prisma 生成的类型可能会变得非常庞大。
具有 50 多个表和深层关系的模式可能导致:
- 编译时间超过几分钟
- 类型检查期间高内存使用
- IDE 响应显著下降
- CI/CD 管道在类型检查时超时
解决方案
解决方案涉及在定义接受 PrismaClient 实例的函数参数时,使用 TypeScript 的 typeof 运算符而不是直接类型引用。(当然,如果您熟悉 TypeScript 类型系统,您可以使用其他方法。)
大型模式的潜在问题方法
import { PrismaClient } from '../prisma/generated/client'
const saveFn = async (prismaClient: PrismaClient) => {
// Function implementation
}
const client = new PrismaClient()
await saveFn(client)
性能影响
- 类型:269,597
- 实例化:2,772,929
- 内存使用:394,718K
- 编译时间:1.86s
使用 typeof 的优化方法
import { PrismaClient } from '../prisma/generated/client'
const saveFn = async (prismaClient: typeof client) => {
// Function implementation
}
const client = new PrismaClient()
await saveFn(client)
性能影响
- 类型:222
- 实例化:152
- 内存使用:146,854K
- 编译时间:0.41s
为什么 typeof 更高效
typeof 运算符通过改变 TypeScript 解析类型的方式,创建了一条更高效的类型解析路径。
- 类型查询引用:
typeof client执行类型查询,获取标识符表达式的扩展类型,避免了重新展开复杂的PrismaClient类型定义。 - 减少类型实例化:编译器避免为每次类型检查扩展整个 Prisma 类型层次结构(导致实例化减少 99.9%)。
- 内存效率:引用现有实例的推断类型比扩展复杂的条件类型和泛型需要显著更少的内存。
结论
在处理大型 Prisma 模式时,直接类型引用和类型查询之间的选择对于保持开发速度至关重要。typeof 方法不仅仅是一种优化,它也是随着数据库模式复杂性增加而扩展 TypeScript 编译性能的一项基本技术。
这里展示的编译时间减少 78% 的效果,随着模式复杂性的增加呈指数级增长,使得这种优化成为在企业级应用程序中保持高效开发工作流的基础。
基准测试
用于验证此分析的完整基准测试代码和测试用例可在 ts-bench 存储库中找到。
https://github.com/ToyB0x/ts-bench/pull/211
与 Prisma 保持联系
通过以下方式与我们保持联系,继续你的 Prisma 之旅: 我们的活跃社区。保持信息灵通,参与其中,并与其他开发人员协作。
- 在 X 上关注我们 获取公告、直播活动和实用技巧。
- 加入我们的 Discord 提问、与社区交流,并通过对话获得积极支持。
- 在 YouTube 上订阅 获取教程、演示和直播。
- 在 GitHub 上参与 加星收藏存储库、报告问题或为问题做出贡献。