跳到主要内容

Drizzle

本页比较了 Prisma ORM 和 Drizzle。

Drizzle vs Prisma ORM

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

Drizzle 是一个传统的 SQL 查询构建器,可让您使用 JavaScript/TypeScript 函数编写 SQL 查询。它可用于查询数据库或运行迁移。Drizzle 还提供 Queries 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 的 Queries 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]'),
})

当执行变更(createupdatedelete)时,Drizzle Queries 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 提供了更通用的运算符集,这些运算符使用起来很直观。

Drizzle 和 Prisma ORM 的过滤 API 如何不同的一个很好的例子是查看 string 过滤器。虽然 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 仅提供限制-偏移分页,而 Prisma ORM 方便地为限制-偏移和基于游标的分页都提供了专用 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 社区开发了大量有用的工具,可帮助完成各种 Prisma 工作流程。以下是一些亮点

数据库支持

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

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

此外,Prisma ORM 支持 CockroachDB、Microsoft SQL Server 和 MongoDB,而 Drizzle 目前不支持。Prisma ORM 还提供 relation mode,允许 Prisma ORM 为那些不支持外键约束的数据库引擎模拟外键约束。Drizzle 目前通过 HTTP Proxy 支持 Cloudflare D1、bun:sqlite 和 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 为数据访问和管理数据库模式提供了一种全面且易于学习的方法。