Drizzle
Prisma 和 Drizzle 在資料庫操作方面採取了不同的方法。Drizzle 吸引那些偏好接近 SQL 編寫查詢的開發者,而 Prisma 則旨在支援構建和維護生產級應用程式的團隊——在這些場景中,清晰性、協作和長期可維護性至關重要。
雖然這兩個庫解決的問題相似,但它們的工作方式截然不同,各有優缺點。選擇哪個將取決於你的專案需求以及對專案重要的具體權衡。
Drizzle vs Prisma ORM
Drizzle 是一個傳統的 SQL 查詢構建器,允許你使用 JavaScript/TypeScript 函式來組合 SQL 查詢。它既可以用於查詢資料庫,也可以用於執行遷移。Drizzle 還提供了一個查詢 API (Queries API),它提供了比 SQL 更高層次的抽象,可用於讀取巢狀關係。Drizzle schema 在 TypeScript 檔案中定義,這些檔案用於生成 SQL 遷移,然後針對資料庫執行。
Prisma ORM 解決了傳統 ORM 的許多問題,例如臃腫的模型例項、業務邏輯與儲存邏輯混淆、缺乏型別安全或因懶載入等導致不可預測的查詢。它使用 Prisma schema 以宣告式方式定義應用程式模型。Prisma Migrate 允許從 Prisma schema 生成 SQL 遷移,並針對資料庫執行。CRUD 查詢由 Prisma Client 提供,這是一個輕量級且完全型別安全的 Node.js 和 TypeScript 資料庫客戶端。
Prisma:為團隊打造
Prisma 旨在幫助團隊更快地交付產品——尤其是在並非所有人都是 SQL 專家的情況下。
- 無 SQL 瓶頸:使用 Prisma,你無需深厚的 SQL 知識即可高效工作。你的整個團隊都可以為後端程式碼做出貢獻——無需依賴某一個人編寫原始查詢或除錯資料庫邏輯。
- 共享心智模型:Prisma 的 schema 易於閱讀和理解。它提供了應用程式資料模型的單一、一致檢視。
- 更簡單的程式碼審查:Schema 變更和資料訪問模式透明且一致,使審查者更容易理解和批准後端更改。
- 可預測的工作流:Prisma 自動化了遷移生成、客戶端型別定義和查詢構建——這樣你的團隊就不必手動完成這些工作。
Drizzle 在瞭解 SQL 或傾向於學習 SQL 的單個開發者手中可能非常棒。但一旦你有了團隊,Prisma 就會消除阻礙你速度的摩擦和知識風險。
型別安全
Drizzle 並非完全型別安全。正如第三方進行的這項 比較研究中所述:“Drizzle 給人一種型別安全的印象。然而,只有查詢結果具有型別資訊。你可以使用 Drizzle 編寫無效查詢。”
藉助 Prisma,由於生成的型別,你可以獲得完全的型別安全。這意味著在編寫程式碼和與團隊成員協作時,出錯的可能性更小。
Prisma Schema 作為單一事實來源
使用 Prisma,你的資料模型位於一個單一檔案中:schema.prisma。
- 顯式化:無需推斷型別或破譯 SQL 生成函式——你的 schema 就在那裡。
- 可讀性強:即使是非技術團隊成員也能理解你的模型和關係。
- 驅動一切:遷移、TypeScript 型別、自動補全、ERD 生成等都來自你的 schema。
相比之下,Drizzle 的 schema 是透過 TypeScript 程式碼構建的,這使得視覺化完整的資料模型更加困難,增加了認知負荷,並可能導致跨程式碼庫定義模型時出現不一致。閱讀更多關於我們為何看好 PSL (Prisma Schema Language) 的內容。
想將你的 schema 檢視為 ERD?使用 Prisma,只需一個命令:npx prisma generate && npx prisma-erd-generator
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 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 方法的一些優點包括
- 透過 fluent 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 都能夠記錄查詢及其生成的底層 SQL。
Prisma ORM 在客戶端中內建了額外功能,幫助團隊更好地理解其資料使用情況。指標和追蹤是兩個可以隨時啟用並提供每個查詢資訊的特性。這些資訊可以與外部工具整合,以便你可以跟蹤隨時間變化的效能。
附加產品
Drizzle 和 Prisma 都提供了與 ORM 配套的產品。Prisma Studio 的釋出旨在允許使用者透過 GUI 與資料庫互動,並允許團隊內部有限的自託管。Drizzle Studio 的釋出旨在完成相同的任務。
除了 Prisma Studio,Prisma 還透過 Prisma 資料平臺提供商業產品
- Prisma Accelerate:一個連線池和全域性快取,與 Prisma ORM 整合。使用者可以立即利用連線池,並可以在單個查詢級別控制快取。
- Prisma Optimize:一個查詢分析工具,提供深度洞察、可操作的建議,並允許你與 Prisma AI 互動以獲取更多洞察並最佳化你的資料庫查詢。
這些產品與 Prisma ORM 協同工作,提供全面的資料工具,透過遵循資料 DX原則,使構建資料驅動型應用程式變得輕鬆。
更安全的變更和更少的缺陷
Prisma 最大限度地減少了在資料庫操作中人為錯誤的風險。
- 重新命名欄位?Prisma 會自動更新 schema、資料庫和生成的客戶端。你將自動保持同步。
- 更改關係?Prisma 生成安全的遷移並透過完整的型別安全強制執行正確性。
團隊選擇 Prisma,因為它強制執行正確性,並幫助你快速前進而不會破壞現有功能。
開箱即用的生態系統
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 工作流。以下是其中幾個亮點
prisma-erd-generator:將 Prisma schema 視覺化為實體關係圖 (ERD)。prisma-zod-generator:從 Prisma schema 生成 Zod schema。bridg:允許你使用 Prisma Client 從前端訪問資料庫。jest-prisma:與 Jest 整合的 Prisma 測試環境。prisma-pothos-types:在使用 GraphQL Pothos 時,基於 Prisma 模型建立 GraphQL 型別。prisma-trpc-generator:從你的 Prisma schema 建立 tRPC 路由器。@cerbos/orm-prisma:根據 Cerbos 的授權策略過濾資料。
Prisma 不僅僅是一個 ORM——它是一個完整的型別安全資料工具包
- Prisma Schema → 遷移、型別和文件
- Prisma Client → 自動補全、完全型別安全的查詢
- Prisma Studio → 一個用於檢查和編輯資料的 GUI
- 原生整合 → PlanetScale、Vercel、Cloudflare D1、Neon 等
資料庫支援
Drizzle 和 Prisma ORM 都支援多種不同型別的資料庫。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 的延遲和吞吐量。透過針對你正在考慮的資料庫或資料庫提供商執行基準測試,你可以清楚地瞭解它們的相對效能特徵,從而幫助做出明智的決定。
此外,你還可以查閱我們構建的基準測試工具上的發現,該工具比較了包括 Drizzle 在內的流行 TypeScript ORM。這個基準測試是開源的,旨在公平比較 Node.js 和 TypeScript 生態系統中資料庫提供商和 ORM 庫之間的資料庫查詢延遲。
結論
是的,我們有偏見,但這也是我們從使用者和客戶那裡聽到的反饋
- “我們從 Drizzle 切換到 Prisma,因為 schema 漂移讓我們苦不堪言。Prisma 就是好用。”
- “多虧了 Prisma 的 schema,我在 2 小時內就讓一名初級開發者上手了。如果用 Drizzle,可能要花幾天時間。”
- “我信任 Prisma 能讓我們的資料庫保持健康。我們團隊中沒有人需要成為 Postgres 專家。”
- “Prisma 團隊更新和新功能的推出速度簡直令人驚歎。”
Drizzle ORM 和 Prisma ORM 都是用於資料訪問和遷移的工具。Drizzle 專注於作為 SQL 風格語法的一個薄包裝層,而 Prisma 則專注於提供便捷和富有表現力的 API。其他重要區別包括 Prisma ORM 對 MSSQL 和 MongoDB 的支援、透過Prisma Client 擴充套件支援附加功能、額外的雲就緒產品以及一個健壯的生態系統。
另一方面,對於由具有不同資料庫經驗水平的開發者(前端、後端和全棧)組成的團隊,Prisma ORM 為資料訪問和資料庫 schema 管理提供了一種全面且易於學習的方法。
與 Prisma 保持聯絡
透過以下方式繼續你的 Prisma 之旅 我們活躍的社群。保持資訊更新,參與其中,並與其他開發者協作
- 在 X 上關注我們 獲取公告、直播活動和實用技巧。
- 加入我們的 Discord 提問、與社群交流,並透過對話獲得積極支援。
- 在 YouTube 上訂閱 獲取教程、演示和直播。
- 在 GitHub 上參與 透過點贊倉庫、報告問題或為問題貢獻程式碼。