第十五章 · 软件的背后

15.3 数据库不是黑盒

本节最后更新:2026-05-13
验证环境:无(原理章节,不依赖特定工具版本)

为什么需要理解数据库

在 Vibe Coding 中,AI 会替你写所有 SQL 语句。你可以永远不学 SQL 语法。

但是,当你的应用变得很慢(加载一个页面要 5 秒),90% 的可能是数据库查询的问题。这时候如果你对数据库有一个简单的心理模型,就能准确地向 AI 描述问题并快速修复。

这个心理模型不需要多深——你只需要知道"数据库是一堆表格"和"索引像书的目录"这两个概念,就能解决 80% 的性能问题。

数据库是怎么工作的

你可以把数据库想象成一个超大型的 Excel 表格集合

当你执行一个查询:

SELECT * FROM users WHERE email = 'alice@example.com';

数据库会做:

  1. 找到 users 这个"表格"
  2. 遍历每一行,检查 email 列是否等于 alice@example.com
  3. 返回所有匹配的行

如果没有索引,数据库要扫描整个表——就像你在 Excel 里从上到下逐行查找。如果表里有 100 万行用户数据,这个查询可能需要几秒钟。

一个重要的认知:数据库不像人类那样"聪明"。 人类看到"找 alice@example.com"会自然地从字母 A 开头的区域开始找。但数据库不会——它会老老实实地从第 1 行开始逐行扫描到最后一行。除非你(或 AI 帮你)告诉它"在 email 列上建一个索引"。

索引:加速查询的关键

索引是数据库最核心的优化手段——也是 AI 生成的代码中经常遗漏的东西。

索引的概念和书的目录一样:没有目录,你要翻遍整本书才能找到"Vibe Coding"这个词出现在哪一页。有目录,直接翻到对应页码。

-- 创建索引——告诉数据库"经常要用 email 查用户,帮我记住每个 email 在哪一行"
CREATE INDEX idx_users_email ON users (email);

创建索引后,上面的 WHERE email = 'alice@example.com' 查询从"扫描 100 万行"变成了"直接跳到对应的那一行",时间从秒级降到毫秒级。

在 Vibe Coding 中检查索引:

你不需要自己写 CREATE INDEX 语句。当你发现页面加载慢时,直接问 AI:

"这个页面加载很慢,是不是数据库缺少索引?帮我检查一下需要在哪里加索引。"

AI 会检查你的 Prisma Schema 或 SQL 查询,在需要的地方添加索引定义。

什么时候需要索引:

什么时候不需要索引:

复合索引(索引进阶):

有时候你经常组合使用两个列来查询:

SELECT * FROM orders WHERE user_id = 123 ORDER BY created_at DESC LIMIT 20;

这时 AI 可能创建一个复合索引(包含两列):

CREATE INDEX idx_orders_user_created ON orders (user_id, created_at);

这个索引同时加速了"按 user_id 筛选"和"按 created_at 排序"两个操作。如果你告诉 AI "查询还是很慢",它可能会建议复合索引。

常见的性能问题模式

N+1 查询问题

这是最常见的性能陷阱:

# 伪代码
posts = db.query("SELECT * FROM posts")  # 1 次查询
for post in posts:
    comments = db.query("SELECT * FROM comments WHERE post_id = ?", post.id)  # N 次查询

如果有 100 篇文章,这个循环会产生 1 + 100 = 101 次查询。用 JOIN 一次就能完成:

SELECT posts.*, comments.*
FROM posts
LEFT JOIN comments ON posts.id = comments.post_id;

AI 经常犯 N+1 错误吗? 是的,尤其在生成 ORM 代码时。解决方案:遇到页面加载慢时,直接问 AI "这个页面是不是有 N+1 查询问题?"

AI 会识别出 ORM 代码中的循环查询模式,并用 include(Prisma)或 JOIN 替换。

N+1 问题的典型症状:

如果你怀疑有 N+1 问题,告诉 AI:

"加载用户列表页面时,Network 面板显示发了 50 个请求,每个请求都是查一个用户的订单数据。这是不是 N+1 问题?"

AI 会确认并修复。

缺少索引

场景:应用刚上线时数据少,一切正常。运行一个月后,数据量增长了 100 倍,页面加载越来越慢。

原因:AI 生成数据表时可能没有考虑你未来的数据量。当数据量增长后,EXPLAIN QUERY PLAN 一看——全是全表扫描。

数据量增长的三个典型阶段:

数据量表现对策
< 1 万行不管有没有索引,查询都很快不需要索引
1 万 ~ 10 万行没有索引时查询变慢在常用查询字段上加索引
> 10 万行必须要有索引,否则查询以秒计检查所有查询的索引覆盖

如何向 AI 描述数据库问题

我的应用首页加载非常慢(约 5 秒),数据表大概有 10 万条记录。
主要的查询是:SELECT * FROM orders WHERE user_id = ? ORDER BY created_at DESC LIMIT 20。
帮我检查这个查询是否需要加索引。

AI 会建议在 user_idcreated_at 上创建复合索引。创建后,查询时间会降到十几毫秒。

更完整的描述模板:

页面:[页面名称] 加载慢,耗时约 [X] 秒。
哪个操作慢:[点击按钮/打开页面/提交表单]。
数据量:orders 表约 [X] 万条记录。
慢的查询(如果知道):[把 SQL 或 ORM 查询贴出来]。
什么时候开始变慢:[一直慢 / 最近数据量大了才慢]。

不需要把所有字段都填满——填你知道的就行。AI 会追问不清楚的细节。

数据库类型的不同

不同类型的数据库在一些细节上不同,但核心概念相同:

数据库适合场景在 Vibe Coding 中
SQLite本地开发、数据量小默认选择——零配置,文件级数据库
PostgreSQL生产环境、数据量大Prisma 连接,Vercel/ Railway 部署
MySQL传统 Web 应用不推荐——易用性不如 PostgreSQL
MongoDB文档型数据AI 也很熟悉,但查询模式不同

你不需要自己选——告诉 AI "这个项目要用什么数据库",AI 会根据项目需求推荐。大多数情况 AI 会推荐 SQLite(开发阶段)+ PostgreSQL(生产环境)的组合。

理解 vs 不必理解

关于数据库,你不需要知道:

关于数据库,你最好知道:

这三个"最好知道"的点,能帮你解决 80% 的数据库性能问题。把症状告诉 AI,AI 做诊断,你做验证。

本节要点
Vibe 练习

对 Claude Code 说:

"我有一个 SQLite 数据库,orders 表有 50 万条数据。查询 SELECT * FROM orders WHERE status = 'pending' ORDER BY created_at DESC 需要 3 秒。请帮我诊断并提供优化方案。"

进阶练习:

让 AI "在我的项目中创建一个简单的演示:创建 10000 条测试数据插入 orders 表,然后分别用有索引和无索引的情况下执行同一个查询,展示查询时间差异。" 这个练习会让你亲眼看到索引的效果——从"秒级"到"毫秒级"的差异。