10.1 核心概念
- 生产迁移策略
- CI/CD 里以
migrate deploy顺序应用迁移,与应用发布解耦、幂等、不重置库。破坏性变更走展开-收缩两步发布。 - seeding(种子数据)
- 用脚本填充初始/示例数据(角色、字典表、演示账号)。在
package.json的prisma.seed配置,migrate reset/db seed时执行。 - N+1 查询
- 取 N 条主记录后又逐条查关系 = 1+N 次往返。用
include/嵌套select合并,或批量in查询消除。 - 索引(index)
- schema 里用
@@index([...])/@unique声明。为高频 where/orderBy/join 列建索引,是最见效的调优手段。 - 查询日志与 metrics
new PrismaClient({ log: ["query"] })打印 SQL 与耗时;$metrics/ 事件监听可接入 Prometheus 观测慢查询与连接池。- binaryTargets
- schema 的
generator里声明目标平台(如debian-openssl-3.0.x),确保 Docker/Lambda 里生成对应查询引擎二进制。 - 部署 checklist
- 上线前逐项核对:迁移、连接串、连接池、日志、备份、回滚方案,减少事故。
10.2 CI/CD 迁移流水线
# 部署脚本(发布前执行,幂等)
$ npx prisma migrate deploy
$ npx prisma generate # 若构建阶段未生成
$ node dist/server.js
# GitHub Actions 片段
- name: Apply migrations
run: npx prisma migrate deploy
env:
DATABASE_URL: ${{ secrets.DATABASE_URL }}
迁移与发布顺序
加列/建表等向后兼容变更可先迁移再发新代码;删列/改类型等破坏性变更须先发能兼容新旧的代码,再迁移,避免滚动发布期间旧实例访问已删列而报错。
10.3 Seeding
// prisma/seed.ts
import { PrismaClient } from "@prisma/client";
const prisma = new PrismaClient();
async function main() {
await prisma.role.createMany({
data: [{ name: "ADMIN" }, { name: "USER" }],
skipDuplicates: true,
});
}
main().finally(() => prisma.$disconnect());
// package.json
{
"prisma": { "seed": "tsx prisma/seed.ts" }
}
# 运行:npx prisma db seed
10.4 性能调优:消除 N+1
// ❌ N+1:循环里逐条查关系
const users = await prisma.user.findMany();
for (const u of users) {
const posts = await prisma.post.findMany({ where: { authorId: u.id } });
}
// ✅ 一次带出关系
const withPosts = await prisma.user.findMany({
include: { posts: true },
});
10.5 索引与慢查询
model Post {
id Int @id @default(autoincrement())
authorId Int
published Boolean @default(false)
createdAt DateTime @default(now())
@@index([authorId]) // 外键 join 常查
@@index([published, createdAt]) // 列表页复合索引
}
看真实 SQL
开 log: ["query"] 观察 Prisma 生成的 SQL 与耗时,再用数据库的 EXPLAIN ANALYZE 定位缺索引/全表扫描。别凭感觉加索引——按实际慢查询加。
10.6 日志与监控
const prisma = new PrismaClient({
log: [{ emit: "event", level: "query" }, "warn", "error"],
});
prisma.$on("query", (e) => {
if (e.duration > 200) console.warn("slow query", e.duration, e.query);
});
10.7 Docker 多阶段构建
# 生成阶段:装依赖并 prisma generate
FROM node:20-slim AS build
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npx prisma generate && npm run build
# 运行阶段
FROM node:20-slim
RUN apt-get update -y && apt-get install -y openssl # 引擎依赖
WORKDIR /app
COPY --from=build /app/node_modules ./node_modules
COPY --from=build /app/dist ./dist
COPY --from=build /app/prisma ./prisma
CMD ["sh", "-c", "npx prisma migrate deploy && node dist/server.js"]
binaryTargets 与 openssl
Prisma 查询引擎依赖 OpenSSL,Alpine/slim 镜像常缺。装好 openssl,并在 generator 里设 binaryTargets = ["native", "debian-openssl-3.0.x"],否则运行时报"引擎找不到/不兼容"。
10.8 上线 Checklist
- CI 里跑
prisma migrate deploy,绝不在生产用migrate dev/reset。 - 破坏性变更走展开-收缩两步发布,先兼容代码后迁移。
- 使用单例 PrismaClient;Serverless 配 PgBouncer/Accelerate,
connection_limit合理。 - 高频 where/join/order 列建
@@index;用查询日志 + EXPLAIN 定位慢查询。 - 关键写入用事务;用户输入原始 SQL 一律参数化
$queryRaw。 - Docker 装 openssl、设 binaryTargets;启动前
migrate deploy。 - 接入慢查询日志/metrics;数据库定期备份并演练回滚。
- 敏感连接串走 secret,不入库、不进前端 bundle。
10.9 结语
至此 10 章走完 Prisma 全景:从 schema.prisma 建模、关系、Migrate 迁移,到类型安全 CRUD、进阶查询、事务与原始 SQL、$extends 扩展、框架集成,直到生产部署。Prisma 的价值在于把"数据模型"变成团队共享、可 review、类型驱动的单一事实来源。若你更看重轻量与贴近 SQL、需要上 Edge,别忘了同站的 Drizzle ORM 完全指南——两把利器,因项目而择。祝你建模愉快。