一、什么是 Drizzle ORM
Drizzle ORM 是一个面向 TypeScript 的轻量级数据库工具链,它同时具备:
- Schema 定义能力------用纯 TypeScript 声明表结构
- Query Builder------链式 API 构建 SQL 查询
- Migration 工具------基于 Schema 差异自动生成迁移文件
- 类型安全贯穿全链路------从 Schema 定义到查询结果,TypeScript 编译器全程保驾护航
与 Prisma 的自定义 Schema 语言(.prisma 文件)不同,Drizzle 回归了"一切皆 TypeScript 代码"的理念,开发者无需学习额外的 DSL,也无需引入代码生成步骤。
二、核心优点
1. 零代码生成,极致编译速度
Prisma 需要 prisma generate 将 Schema 编译为客户端代码,项目越大耗时越长。Drizzle 完全跳过这一步------Schema 本身就是 TypeScript 代码,类型推导由 TypeScript 编译器原生完成,无需中间层。
2. SQL 优先,不隐藏底层
Drizzle 的查询 API 与原生 SQL 几乎一一映射:
TypeScript
// Drizzle 查询
db.select().from(users).where(eq(users.email, "test@example.com"));
// 对应的 SQL
// SELECT * FROM users WHERE email = 'test@example.com';
对于熟悉 SQL 的开发者,几乎没有心智负担。遇到复杂查询时,还可以直接嵌入原生 SQL 片段,不会被 ORM 的抽象层束缚。
3. 运行时极致轻量
Drizzle 的核心包体积极小(gzip 后约 7KB),冷启动几乎不增加额外延迟。相比之下,Prisma Client 动辄数 MB 的运行时在 Serverless 环境下可能成为性能瓶颈。
4. 多数据库统一接口
Drizzle 支持 PostgreSQL、MySQL、SQLite、PlanetScale、Neon、Turso、Cloudflare D1 等主流数据库,切换数据库只需更换对应的驱动适配器,Schema 和查询语法保持一致。
5. 关系查询的类型推导
Drizzle 的 relations API 能自动推导出关联数据的嵌套类型。来看一个直观对比:
TypeScript
// 定义关系
const usersRelations = relations(users, ({ many }) => ({
posts: many(posts),
}));
// 查询用户及其所有文章------结果类型自动推导为 { id, name, posts: Post[] }
const result = await db.query.users.findMany({
with: { posts: true },
});
// result[0].posts 的类型自动推导,无需手动声明
6. Drizzle Kit:可视化的数据库管理
Drizzle Kit 是配套的 CLI 工具,提供:
- Introspect:从已有数据库反向生成 TypeScript Schema
- Generate:对比 Schema 变更自动生成 SQL 迁移文件
- Push:直接将 Schema 变更应用到数据库(适合开发阶段快速迭代)
- Studio:内置的数据库可视化管理面板(npx drizzle-kit studio)
三、适用场景
| 场景 | 说明 |
|---|
|-------------------|--------------------------------------------------|
| Serverless 应用 | 轻量运行时不拖累冷启动,适配 Cloudflare Workers / AWS Lambda 等 |
| 边缘计算 | 原生支持 Cloudflare D1、Turso 等边缘数据库 |
| 类型敏感型项目 | 追求全链路类型安全,希望编译期拦截 SQL 错误 |
| SQL 经验丰富的团队 | 不想被 ORM 屏蔽 SQL 细节,需要灵活拼接复杂查询 |
| 微服务 / 中小型项目 | Schema 不复杂但需要高效率开发,讨厌代码生成环节 |
| 已有数据库的项目 | 通过 Introspect 反向生成 Schema,渐进式引入 |
暂不适合的场景:团队完全不懂 SQL、需要 ORM 完全隐藏数据库细节(此时 Prisma 的抽象层更友好)。
四、具体使用方式
环境准备
bash
# 初始化项目
npm init -y
npm install drizzle-orm better-sqlite3
npm install -D drizzle-kit @types/better-sqlite3
第一步:定义 Schema
创建 src/db/schema.ts:
TypeScript
import { sqliteTable, text, integer } from "drizzle-orm/sqlite-core";
export const users = sqliteTable("users", {
id: integer("id").primaryKey({ autoIncrement: true }),
name: text("name").notNull(),
email: text("email").notNull().unique(),
createdAt: integer("created_at", { mode: "timestamp" })
.notNull()
.default(sql`(unixepoch())`),
});
export const posts = sqliteTable("posts", {
id: integer("id").primaryKey({ autoIncrement: true }),
title: text("title").notNull(),
content: text("content").notNull(),
authorId: integer("author_id")
.notNull()
.references(() => users.id),
publishedAt: integer("published_at", { mode: "timestamp" }),
});
第二步:定义关系(可选但推荐)
在 src/db/schema.ts 中追加:
TypeScript
import { relations, sql } from "drizzle-orm";
export const usersRelations = relations(users, ({ many }) => ({
posts: many(posts),
}));
export const postsRelations = relations(posts, ({ one }) => ({
author: one(users, {
fields: [posts.authorId],
references: [users.id],
}),
}));
第三步:初始化数据库连接
创建 src/db/index.ts:
TypeScript
import { drizzle } from "drizzle-orm/better-sqlite3";
import Database from "better-sqlite3";
import * as schema from "./schema";
const sqlite = new Database("local.db");
export const db = drizzle(sqlite, { schema });
第四步:执行迁移
bash
# 生成迁移文件
npx drizzle-kit generate
# 执行迁移
npx drizzle-kit push
第五步:编写业务代码
TypeScript
import { db } from "./db";
import { users, posts } from "./db/schema";
import { eq, and, like, desc } from "drizzle-orm";
// 插入用户
const [newUser] = await db.insert(users).values({
name: "张三",
email: "zhangsan@example.com",
}).returning();
// 查询(全链路类型推导)
const allUsers = await db.select().from(users);
// 条件查询
const matched = await db.select()
.from(users)
.where(like(users.name, "%张%"));
// 联表查询(利用 relations)
const usersWithPosts = await db.query.users.findMany({
with: { posts: true },
where: eq(users.name, "张三"),
});
// usersWithPosts[0].posts 类型自动推导为 Post[]
// 更新
await db.update(users)
.set({ name: "张三丰" })
.where(eq(users.id, newUser.id));
// 删除
await db.delete(posts).where(eq(posts.id, 1));
第六步:使用 Drizzle Studio 可视化
bash
npx drizzle-kit studio
浏览器打开 https://local.drizzle.studio,即可在图形界面中浏览和编辑数据。
五、与主流方案对比
| 维度 | Drizzle ORM | Prisma | TypeORM | Knex |
|---|
|--------------|---------------|---------|--------|------------|
| Schema 定义 | TypeScript 原生 | 自定义 DSL | 装饰器/代码 | 无 Schema 层 |
| 代码生成 | 不需要 | 需要 | 需要 | 不需要 |
| 类型安全 | 全链路 | 强(生成后) | 中等 | 弱 |
| SQL 控制力 | 极高 | 中 | 中 | 极高 |
| 运行时体积 | ~7KB | ~5MB+ | ~1MB | ~200KB |
| 学习曲线 | 平缓(懂 SQL 即上手) | 需要学 DSL | 陡峭 | 平缓 |
| Edge Runtime | 原生支持 | 部分支持 | 不支持 | 支持 |
六、总结
Drizzle ORM 的出现改变了 TypeScript 数据库工具链的格局。它在"类型安全"与"贴近 SQL"之间找到了精准的平衡点:不像 Prisma 那样试图用抽象层包裹一切,也不像 Knex 那样完全放弃类型推导。
对于追求轻量、极速、类型安全且对 SQL 有基本掌握的团队,Drizzle ORM 是一个值得在生产环境投入的选择。它的生态仍在快速演进中------Drizzle Kit Studio、Seeding 工具、Zod Schema 联动等周边能力正持续完善。
如果你正在新建一个 TypeScript 后端项目,不妨给它 30 分钟尝试一次 drizzle-kit introspect 或从零建一个 Schema------那种"写 TypeScript 就是写 Schema"的流畅感,试过就很难回去了。