Drizzle
本頁比較 Prisma ORM 和 Drizzle。
Drizzle vs Prisma ORM
雖然 Prisma ORM 和 Drizzle 解決相似的問題,但它們運作方式非常不同,各有優缺點。選擇哪一個將取決於您專案的需求以及對其重要的確切權衡取捨。
Drizzle 是一個傳統的 SQL 查詢建構器,可讓您使用 JavaScript/TypeScript 函數組合 SQL 查詢。它可以用於查詢資料庫或執行遷移。Drizzle 還提供 Queries API,它提供比 SQL 更高層次的抽象,可用於讀取巢狀關聯。Drizzle schema 在 TypeScript 檔案中定義,這些檔案用於產生 SQL 遷移,然後針對資料庫執行。
Prisma ORM 減輕了傳統 ORM 的許多問題,例如臃腫的模型實例、混合業務與儲存邏輯、缺乏類型安全或由延遲載入等引起的不可預測的查詢。它使用 Prisma schema 以宣告式方式定義應用程式模型。然後,Prisma Migrate 允許從 Prisma schema 產生 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 一起工作,以處理任何所需的抽象層級。
雖然使用 TypedSQL 在 Prisma ORM 中可以使用完全類型化的 SQL 查詢,但以下章節將檢視一些範例,說明 Prisma 和 Drizzle API 的差異,以及在這些情況下 Prisma ORM 的 API 設計原理是什麼。
資料模型建立
Prisma 模型在 Prisma schema 中定義,而 Drizzle 使用 TypeScript 函數進行表定義。然後匯出這些函數並在查詢中使用。
Prisma 產生一個輕量級的資料庫客戶端,它公開了一個量身定制且完全類型安全的 API,用於讀取和寫入在 Prisma schema 中定義的模型的資料,遵循 DataMapper ORM 模式。
Prisma ORM 的資料模型建立 DSL 精簡、簡單且直觀易用。在 VS Code 中建立資料模型時,您可以進一步利用 Prisma ORM 強大的 VS Code 擴充功能,它具有自動完成、快速修復、跳到定義以及其他提高開發人員生產力的優勢。另一方面,Drizzle 使用 TypeScript 意味著您可以利用 TypeScript 的強大功能來獲得額外的靈活性(例如通過重複使用的程式碼)。
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])
}
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,這兩種方法非常相似
// 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: 'nilu@prisma.io' },
})
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, 'nilu@prisma.io'),
})
在執行變更(create
、update
或 delete
)時,Drizzle Queries API 不可用。在這些情況下,您需要使用 Drizzle 類似 SQL 的 API
// create a user
const user = await prisma.user.create({
data: {
name: 'Nilu',
email: 'nilu@prisma.io',
},
})
// update a user
const user = await prisma.user.update({
where: { email: 'nilu@prisma.io' },
data: { name: 'Another Nilu' },
})
// delete a user
const deletedUser = await prisma.user.delete({
where: { email: 'nilu@prisma.io' },
})
// create a user
const user = await db.insert(users).values({
name: 'Nilu',
email: 'nilu@prisma.io',
})
// update a user
const user = await db
.update(users)
.set({ name: 'Another Nilu' })
.where(eq(users.email, 'nilu@prisma.io'))
.returning()
// delete a user
const deletedUser = await db
.delete(users)
.where(eq(users.email, 'nilu@prisma.io'))
.returning()
關聯
使用通過外鍵連線的記錄在 SQL 中可能會變得非常複雜。Prisma ORM 的 虛擬關聯欄位 概念使應用程式開發人員能夠以直觀和方便的方式處理相關資料。Prisma ORM 方法的一些優點是
- 通過流暢的 API 遍歷關聯 (文件)
- 允許更新/建立連線記錄的巢狀寫入 (文件)
- 對相關記錄應用篩選器 (文件)
- 輕鬆且類型安全地查詢巢狀資料,而無需擔心底層 SQL (文件)
- 基於模型及其關聯建立巢狀 TypeScript 類型 (文件)
- 通過關聯欄位在資料模型中直觀地建立關聯模型 (文件)
- 隱式處理關聯表(也稱為 JOIN、link、pivot 或 junction 表)(文件)
const posts = await prisma.post.findMany({
include: {
author: true,
},
})
const posts = await db.query.posts.findMany({
with: {
author: true,
},
})
篩選
Drizzle 公開了給定 SQL 方言的底層篩選器和條件運算符。另一方面,Prisma ORM 提供了一組更 通用的運算符,這些運算符直觀易用。
一個很好的例子說明了 Drizzle 和 Prisma ORM 的篩選 API 如何不同,那就是查看 string
篩選器。雖然 Drizzle 為 like
和 ilike
提供篩選器,但 Prisma ORM 提供了更具體的運算符,開發人員可以使用,例如:contains
、startsWith
和 endsWith
。
// 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',
},
})
// 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'))
const posts = await prisma.post.findMany({
where: {
title: {
contains: 'Hello World',
},
},
})
const posts = await db
.select()
.from(posts)
.where(ilike(posts.title, '%Hello World%'))
const posts = await prisma.post.findMany({
where: {
title: {
startsWith: 'Hello World',
},
},
})
const posts = await db
.select()
.from(posts)
.where(ilike(posts.title, 'Hello World%'))
const posts = await prisma.post.findMany({
where: {
title: {
endsWith: 'Hello World',
},
},
})
const posts = await db
.select()
.from(posts)
.where(ilike(posts.title, '%Hello World'))
分頁
Drizzle 僅提供限制偏移分頁,而 Prisma ORM 方便地為限制偏移和基於游標的分頁提供專用 API。您可以在文件中的 分頁 章節中了解有關這兩種方法的更多資訊。
// 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,
})
// 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 也被許多元框架和開發平台選為資料層工具,例如 Amplication、Wasp、RedwoodJS、KeystoneJS、Remix 和 t3 stack。
由於其成熟度,Prisma 的社群開發了 大量有用的工具,可協助處理各種 Prisma 工作流程。以下是一些重點
zenstack
:工具組,通過 Prisma schema 中的存取控制策略、自動產生的 CRUD API 和前端查詢掛鉤來擴充 Prisma。prisma-erd-generator
:將 Prisma schema 可視化為實體關係圖 (ERD)。prisma-zod-generator
:從 Prisma schema 產生 Zod schema。bridg
:讓您可以從前端使用 Prisma Client 存取您的資料庫。jest-prisma
:用於 Prisma 整合測試的環境,搭配 Jest。prisma-pothos-types
:在使用 GraphQL Pothos 時,基於 Prisma 模型建立 GraphQL 類型。prisma-trpc-generator
:從您的 Prisma schema 建立 tRPC 路由器。@cerbos/orm-prisma
:根據來自 Cerbos 的授權策略篩選資料。
資料庫支援
Drizzle 和 Prisma ORM 都支援多種不同類型的資料庫。Drizzle 通過 Drizzle 建立的驅動程式實作來實現此支援,這些實作與現有的第三方資料庫驅動程式整合。
Prisma ORM 已開始添加對 第三方資料庫驅動程式 的支援,但主要使用 內建驅動程式 與底層資料庫進行通訊。Prisma 還預設將連線設定為 TLS,這提高了安全性。
此外,Prisma ORM 支援 CockroachDB、Microsoft SQL Server 和 MongoDB,而 Drizzle 目前不支援。Prisma ORM 還提供 關聯模式,允許 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 為資料存取和管理資料庫 schema 提供了一種全面且易於學習的方法。