Skip to main content

使用大型 Prisma 模式优化 TypeScript 性能

¥Optimizing TypeScript performance with large Prisma schemas

在 Prisma 应用中处理大型数据库模式时,只需简单更改类型定义策略即可带来显著的性能提升:

¥When working with large database schemas in Prisma applications, a simple change in the type definition strategy can deliver massive performance improvements:

方法类型实例化内存编译时间
直接引用269,5972,772,929395MB1.86s
typeof 技术222(减少 99.9%)152(减少 99.9%)147MB(减少 62%)0.41 秒(减少 78%)

(性能已使用 tsc --noEmit --extendedDiagnostics 验证。)

¥(Performance was verified using tsc --noEmit --extendedDiagnostics.)

本指南向你展示如何使用 TypeScript 的 typeof 运算符(而不是直接类型引用)来实现这些显著的性能提升。

¥This guide shows you how to achieve these dramatic performance gains using TypeScript's typeof operator instead of direct type references.

测试模式概述

¥Test schema overview

性能测量使用精心设计的复杂 Prisma 模式进行,该模式包含 30 个相互关联的模型,从而创建了深层关系链:

¥The performance measurements were conducted using a deliberately complex Prisma schema with 30 interconnected models creating deep relationship chains:

// 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 编译进行压力测试,模拟具有广泛表关系的真实企业应用。

¥This schema creates complex type dependencies that stress-test TypeScript compilation, simulating real-world enterprise applications with extensive table relationships.

问题

¥Problem

在具有广泛数据库模式的企业应用中 - 例如拥有数百种产品变体的电子商务平台、具有复杂的交易层次结构的金融系统或具有错综复杂关系网的内容管理系统 - Prisma 生成的类型可能会非常庞大。

¥In enterprise applications with extensive database schemas—think e-commerce platforms with hundreds of product variants, financial systems with complex transaction hierarchies, or content management systems with intricate relationship webs—Prisma's generated types can become enormous.

包含 50 多个表和深度关系的模式可以实现:

¥A schema with 50+ tables and deep relationships can lead to:

  • 编译时间超过几分钟

    ¥Compilation times exceeding several minutes

  • 类型检查期间内存使用率高

    ¥High memory usage during type checking

  • IDE 响应速度显著下降

    ¥IDE responsiveness degrading significantly

  • CI/CD 流水线因类型检查超时

    ¥CI/CD pipelines timing out on type checks

解决方案

¥Solution

解决方案是在定义接受 PrismaClient 实例的函数参数时使用 TypeScript 的 typeof 运算符,而不是直接类型引用。(当然,如果你熟悉 TypeScript 类型系统,也可以使用其他方法。)

¥The solution involves using TypeScript's typeof operator instead of direct type references when defining function parameters that accept PrismaClient instances. (Of course, if you're familiar with the TypeScript type system, you can use other methods.)

大型模式的棘手方法

¥Problematic approach for large schemas

import { PrismaClient } from '@prisma/client'

const saveFn = async (prismaClient: PrismaClient) => {
// Function implementation
}

const client = new PrismaClient()
await saveFn(client)

性能影响:

¥Performance impact:

  • 类型:269,597

    ¥Types: 269,597

  • 实例化:2,772,929

    ¥Instantiations: 2,772,929

  • 内存使用情况:394,718K

    ¥Memory usage: 394,718K

  • 编译时间:1.86s

    ¥Compilation time: 1.86s

使用 typeof 的优化方法

¥Optimized approach with typeof

import { PrismaClient } from '@prisma/client'

const saveFn = async (prismaClient: typeof client) => {
// Function implementation
}

const client = new PrismaClient()
await saveFn(client)

性能影响:

¥Performance impact:

  • 类型:222

    ¥Types: 222

  • 实例化:152

    ¥Instantiations: 152

  • 内存使用情况:146,854K

    ¥Memory usage: 146,854K

  • 编译时间:0.41s

    ¥Compilation time: 0.41s

为什么 typeof 更高效

¥Why typeof is more efficient

typeof 运算符通过改变 TypeScript 解析类型的方式来创建更高效的类型解析路径:

¥The typeof operator creates a more efficient type resolution path by changing how TypeScript resolves types:

  1. 类型查询参考:typeof client 执行类型查询以获取标识符表达式的扩展类型,从而无需重新扩展复杂的 PrismaClient 类型定义。

    ¥Type Query Reference: typeof client performs a type query that obtains the widened type of the identifier expression, avoiding the need to re-expand the complex PrismaClient type definition

  2. 精简类型实例化:编译器避免了每次类型检查时扩展整个 Prisma 类型层次结构(从而将实例化次数减少了 99.9%)

    ¥Reduced Type Instantiation: The compiler avoids expanding the entire Prisma type hierarchy for each type check (resulting in a 99.9% reduction in instantiations)

  3. 内存效率:引用现有实例的推断类型所需的内存比扩展复杂的条件类型和泛型要少得多。

    ¥Memory Efficiency: Referencing an existing instance's inferred type requires significantly less memory than expanding complex conditional types and generics

结论

¥Conclusion

处理大型 Prisma 模式时,在直接类型引用和类型查询之间进行选择对于保持开发速度至关重要。typeof 方法不仅仅是一种优化,它还是随着数据库模式复杂度的增加,扩展 TypeScript 编译性能的一项重要技术。

¥When working with large Prisma schemas, the choice between direct type references and type queries becomes crucial for maintaining development velocity. The typeof approach isn't just an optimization—it's an essential technique for scaling TypeScript compilation performance as your database schema grows in complexity.

这里演示的 78% 编译时间缩短随着模式复杂性的增加而呈指数级增长,这使得这种优化成为在企业级应用中维护高效开发工作流程的基础。

¥The 78% compilation time reduction demonstrated here scales exponentially with schema complexity, making this optimization foundational for maintaining an efficient development workflow in enterprise-scale applications.

基准测试

¥Benchmark

用于验证此分析的完整基准代码和测试用例可在 ts-bench 存储库中找到:https://github.com/ToyB0x/ts-bench/pull/211

¥The complete benchmark code and test cases used to verify this analysis are available in the ts-bench repository:
https://github.com/ToyB0x/ts-bench/pull/211


Stay connected with Prisma

Continue your Prisma journey by connecting with our active community. Stay informed, get involved, and collaborate with other developers:

We genuinely value your involvement and look forward to having you as part of our community!