跳至主要内容

Drizzle

本页对比了 Prisma ORM 和 Drizzle。

Drizzle 与 Prisma ORM

虽然 Prisma ORM 和 Drizzle 解决的是类似的问题,但它们的工作方式截然不同,并且各有优缺点。选择哪一个取决于项目的需要以及对项目而言重要的具体权衡。

**Drizzle** 是一种传统的 SQL 查询构建器,它允许你使用 JavaScript/TypeScript 函数来组合 SQL 查询。它可以用来查询数据库或运行迁移。Drizzle 还提供了一个查询 API,它提供了一个比 SQL 更高级别的抽象,可以用来读取嵌套关系。Drizzle 模式定义在 TypeScript 文件中,这些文件用于生成 SQL 迁移,然后执行到数据库中。

**Prisma ORM** 缓解了许多传统 ORM 的问题,例如臃肿的模型实例、混合业务与存储逻辑、缺乏类型安全或由延迟加载等引起的不可预测的查询。它使用 Prisma 模式 以声明的方式定义应用程序模型。然后,Prisma Migrate 允许从 Prisma 模式生成 SQL 迁移,并将其执行到数据库中。CRUD 查询由 Prisma Client 提供,Prisma Client 是一个轻量级且完全类型安全的 Node.js 和 TypeScript 数据库客户端。

类型安全

Drizzle 不是 *完全* 类型安全的。正如第三方在 这份对比研究 中引用的那样,“Drizzle 给人一种类型安全的印象。但是,只有查询结果具有类型信息。你可以使用 Drizzle 编写无效的查询。”

使用 Prisma,由于生成的类型,你可以获得 *完全* 的类型安全。这意味着,在编写代码和与团队成员协作时,潜在错误会更少。

API 设计与抽象级别

Drizzle 和 Prisma ORM 在不同的抽象级别上运行。Drizzle 的理念是“如果你了解 SQL,你就了解 Drizzle ORM”。它的 API 镜像了 SQL,而 Prisma Client 提供了一个更高级别的抽象,该抽象是根据应用程序开发人员的常见任务设计的。Prisma ORM 的 API 设计很大程度上依赖于 让正确的事情变得简单 的理念。

虽然 Prisma Client 在更高级别的抽象上运行,但你可以在任何时候降级到 原始 SQL。但是,完全使用 Prisma ORM 和开发你的应用程序不需要 SQL 知识。Prisma ORM 的目标是构建一个专注于开发者体验和生产力的查询语法,这种语法对于开发者来说感觉很熟悉。你可以在这里了解更多信息:为什么选择 Prisma

对于无法在 Prisma Client API 中表达的少数查询,Prisma ORM 还提供了 TypedSQL,它通过直接利用 .sql 文件提供了更熟悉和类型安全的体验。你现有的 SQL 工具和工作流程可以与 Prisma Client 协同工作,以处理任何所需的抽象级别。

虽然 Prisma ORM 中可以使用 TypedSQL 提供完全类型的 SQL 查询,但以下部分将检查 Prisma 和 Drizzle API 在某些方面的差异以及 Prisma ORM API 设计的原理。

数据建模

Prisma 模型定义在 Prisma 模式 中,而 Drizzle 使用 TypeScript 函数来定义表。然后导出这些函数并在查询中使用。

Prisma 生成一个轻量级的数据库客户端,该客户端公开了一个定制的、完全类型安全的 API,用于读取和写入在 Prisma 模式中定义的模型的数据,遵循 DataMapper ORM 模式。

Prisma ORM 的数据建模 DSL 简洁、简单且易于使用。在 VS Code 中建模数据时,你还可以利用 Prisma ORM 功能强大的 VS Code 扩展,该扩展具有自动完成功能、快速修复、跳转到定义以及其他提高开发者生产力的优势。另一方面,Drizzle 使用 TypeScript,这意味着你可以依靠 TypeScript 的强大功能来获得额外的灵活性(例如通过重用代码)。

Prisma ORM
model User {
id Int @id @default(autoincrement())
name String?
email String @unique
posts Post[]
}

model Post {
id Int @id @default(autoincrement())
title String
content String?
published Boolean @default(false)
authorId Int?
author User? @relation(fields: [authorId], references: [id])
}
Drizzle
import {
boolean,
integer,
pgTable,
serial,
text,
uniqueIndex,
varchar,
} from 'drizzle-orm/pg-core'

export const users = pgTable('users', {
id: serial('id').primaryKey(),
name: varchar('name', { length: 256 }),
email: varchar('email', { length: 256 }).unique(),
})

export const posts = pgTable('posts', {
id: serial('id').primaryKey(),
title: varchar('title', { length: 256 }).notNull(),
content: text('content'),
published: boolean('published'),
authorId: integer('author_id').references(() => users.id),
})

迁移

Drizzle 和 Prisma ORM 之间的迁移工作方式类似。这两种工具都遵循基于提供的模型定义生成 SQL 文件的方法,并提供一个 CLI 来将其执行到数据库中。在执行迁移之前,可以修改 SQL 文件,以便使用任一迁移系统执行任何自定义数据库操作。

查询

在 Drizzle 和 Prisma ORM 中,构建纯查询都很自然。使用 Drizzle 的查询 API,这两种方法非常相似。

Prisma ORM
// find all users
const allUsers = await prisma.user.findMany()

// find a single user
const user = await prisma.user.findFirst({
where: { id: 27 },
})

// find a unique user
const user = await prisma.user.findUnique({
where: { email: '[email protected]' },
})
Drizzle
import { eq } from 'drizzle-orm'

// find all users
const allUsers = await db.query.users.findMany()

// find a single user
const user = await db.query.users.findFirst({
where: eq(users.id, 1),
})

// find a unique post
const user = await db.query.users.findFirst({
where: eq(users.email, '[email protected]'),
})

在执行突变(创建、更新或删除)时,Drizzle 查询 API 不可用。在这些情况下,你需要使用 Drizzle 的类似 SQL 的 API。

Prisma ORM
// create a user
const user = await prisma.user.create({
data: {
name: 'Nilu',
email: '[email protected]',
},
})

// update a user
const user = await prisma.user.update({
where: { email: '[email protected]' },
data: { name: 'Another Nilu' },
})

// delete a user
const deletedUser = await prisma.user.delete({
where: { email: '[email protected]' },
})
Drizzle
// create a user
const user = await db.insert(users).values({
name: 'Nilu',
email: '[email protected]',
})

// update a user
const user = await db
.update(users)
.set({ name: 'Another Nilu' })
.where(eq(users.email, '[email protected]'))
.returning()

// delete a user
const deletedUser = await db
.delete(users)
.where(eq(users.email, '[email protected]'))
.returning()

关系

在 SQL 中,处理通过外键连接的记录可能会变得非常复杂。Prisma ORM 的 虚拟关系字段 概念为应用程序开发人员提供了一种直观便捷的方式来处理相关数据。Prisma ORM 方法的一些好处是

  • 通过流畅 API 遍历关系(文档
  • 嵌套写入,允许更新/创建连接的记录(文档
  • 对相关记录应用过滤器(文档
  • 轻松且类型安全地查询嵌套数据,而无需担心底层 SQL(文档
  • 基于模型及其关系创建嵌套 TypeScript 类型(文档
  • 通过关系字段在数据模型中直观地建模关系(文档
  • 隐式处理关系表(有时也称为 JOIN、链接、枢纽或联接表)(文档
Prisma ORM
const posts = await prisma.post.findMany({
include: {
author: true,
},
})
Drizzle
const posts = await db.query.posts.findMany({
with: {
author: true,
},
})

过滤

Drizzle 公开了给定 SQL 方言的底层过滤器和条件运算符。另一方面,Prisma ORM 提供了一组更 通用的运算符,这些运算符易于使用。

查看 string 过滤器是了解 Drizzle 和 Prisma ORM 过滤 API 如何不同的一个很好的例子。虽然 Drizzle 提供了 likeilike 的过滤器,但 Prisma ORM 提供了开发者可以使用的更具体的运算符,例如:containsstartsWithendsWith

Prisma ORM
// case sensitive filter
const posts = await prisma.post.findMany({
where: {
title: 'Hello World',
},
})

// case insensitive filter
const posts = await prisma.post.findMany({
where: {
title: 'Hello World',
mode: 'insensitive',
},
})
Drizzle
// case sensitive filter
const posts = await db
.select()
.from(posts)
.where(like(posts.title, 'Hello World'))

// case insensitive filter
const posts = await db
.select()
.from(posts)
.where(ilike(posts.title, 'Hello World'))
Prisma ORM
const posts = await prisma.post.findMany({
where: {
title: {
contains: 'Hello World',
},
},
})
Drizzle
const posts = await db
.select()
.from(posts)
.where(ilike(posts.title, '%Hello World%'))
Prisma ORM
const posts = await prisma.post.findMany({
where: {
title: {
startsWith: 'Hello World',
},
},
})
Drizzle
const posts = await db
.select()
.from(posts)
.where(ilike(posts.title, 'Hello World%'))
Prisma ORM
const posts = await prisma.post.findMany({
where: {
title: {
endsWith: 'Hello World',
},
},
})
Drizzle
const posts = await db
.select()
.from(posts)
.where(ilike(posts.title, '%Hello World'))

分页

Drizzle 只提供 limit-offset 分页,而 Prisma ORM 方便地为 limit-offset 和基于游标的两种方法都提供了专用的 API。你可以在文档的 分页 部分了解更多关于这两种方法的信息。

Prisma ORM
// limit-offset pagination
const postPage = await prisma.post.findMany({
where: {
title: 'Hello World',
},
skip: 6,
take: 3,
})

// cursor-based pagination
const postPage = await prisma.post.findMany({
where: {
title: 'Hello World',
},
cursor: { id: 7 },
take: 3,
})
Drizzle
// limit-offset pagination (cursor-based not currently possible)
const postPage = await db
.select()
.from(users)
.where(ilike(posts.title, 'Hello World%'))
.limit(3)
.offset(6)

可观察性

Drizzle 和 Prisma ORM 都能够记录查询和生成的底层 SQL。

Prisma ORM 在客户端中内置了其他功能,可以帮助团队更好地了解其数据使用情况。 指标跟踪 是可以在任何时候启用的两个功能,它们可以为你提供每个查询的信息。这些信息可以与外部工具集成,以便你可以跟踪一段时间内的性能。

其他产品

Drizzle 和 Prisma 都在 ORM 之外提供了产品。Prisma Studio 的发布是为了允许用户通过 GUI 与他们的数据库交互,并且还允许有限的自托管以供团队内部使用。Drizzle Studio 的发布是为了完成同样的任务。

除了 Prisma Studio 之外,Prisma 还通过 Prisma Data Platform 提供商业产品。

  • Prisma Accelerate:一个与 Prisma ORM 集成的连接池和全局缓存。用户可以立即利用连接池,并可以在单个查询级别控制缓存。
  • Prisma Pulse:一个变更数据捕获 (CDC) 服务,Prisma Client 可以订阅数据库更改并实时接收它们,几乎无需任何设置。
  • Prisma Optimize:一个查询分析工具,提供深入的见解、可操作的建议,并允许您与 Prisma AI 交互以获得进一步的见解并优化您的数据库查询。

这些产品与 Prisma ORM 协同工作,提供全面的数据工具,通过遵循 Data DX 原则,使构建数据驱动型应用程序变得容易。

生态系统

Drizzle 和 Prisma ORM 都有用户希望执行库未直接支持的操作的情况。Drizzle 依靠 SQL 的表达能力来避免这些情况,而 Prisma ORM 则具有 Prisma Client 扩展,允许任何用户向其 Prisma Client 实例添加其他行为。这些扩展也是可共享的,这意味着团队可以开发它们以在他们的项目中使用,甚至可以供其他团队使用。

虽然 Drizzle 是一款相对较新的产品,但 Prisma ORM 于 2021 年发布,并且在 JavaScript/TypeScript 领域已得到良好建立。它具有已验证的价值,许多公司都信任 生产环境中的 Prisma ORM

Prisma ORM 还是许多元框架和开发平台(如 AmplicationWaspRedwoodJSKeystoneJSRemixt3 stack)的首选数据层工具。

由于其成熟度,Prisma 的社区开发了 大量有用的工具,有助于各种 Prisma 工作流程。以下是一些亮点。

数据库支持

Drizzle 和 Prisma ORM 都支持多种不同类型的数据库。Drizzle 通过 Drizzle 创建的驱动程序实现来实现此支持,这些实现与现有的第三方数据库驱动程序集成。

Prisma ORM 已经开始添加对 第三方数据库驱动程序 的支持,但主要使用 内置驱动程序 与底层数据库通信。Prisma 还默认将连接设置为 TLS,从而提高安全性。

此外,Prisma ORM 支持 CockroachDB、Microsoft SQL Server 和 MongoDB,而 Drizzle 目前不支持。Prisma ORM 还提供 关系模式,允许 Prisma ORM 为不支持它的数据库引擎模拟外键约束。Drizzle 目前支持 Cloudflare D1、bun:sqlite 和通过 HTTP 代理的 SQLite,而 Prisma ORM 目前不支持。

基准测试

我们理解性能是选择 ORM 时需要考虑的关键因素。要比较各种 ORM 的性能,您可以使用 Vercel 托管的开源 数据库延迟基准测试工具。此工具允许您在不同工作负载和配置下评估各种 ORM 的延迟和吞吐量。通过针对您正在考虑的数据库或数据库提供商运行基准测试,您可以清楚地了解其相对性能特征,从而帮助您做出明智的决策。

或者,您还可以查看我们构建的 基准测试工具 上的结果,该工具比较了流行的 TypeScript ORM,包括 Drizzle。此基准测试是开源的,旨在公平地比较 Node.js 和 TypeScript 生态系统中数据库提供商和 ORM 库之间的数据库查询延迟。

结论

Drizzle ORM 和 Prisma ORM 都是用于数据访问和迁移的工具。Drizzle 侧重于成为 SQL 类语法的薄包装器,而 Prisma 则侧重于提供便捷且富有表现力的 API。其他重要区别包括 Prisma ORM 支持 MSSQL 和 MongoDB,通过Prisma Client 扩展支持更多功能,提供更多云就绪产品,以及强大的生态系统。

另一方面,对于由具有不同数据库经验水平的开发人员(前端、后端和全栈)组成的团队,Prisma ORM 提供了一种全面且易于学习的数据访问和数据库模式管理方法。