你以为ORM让你少写SQL,其实你的数据库正在为你的便利买单

2026-10-10 16 0

你以为ORM让你少写SQL,其实你的数据库正在为你的"便利"买单

先讲个真实故事。

前阵子朋友公司上线了一个新功能,用户量也就几万。结果数据库CPU直接打满,接口响应时间从200ms飙到十几秒。DBA排查了一圈,最后把问题定位到一段看似"优雅"的代码——用ORM写的批量查询。

const users = await User.findAll();
for (const user of users) {
  const orders = await Order.findAll({ where: { userId: user.id } });
  result.push({ user, orders });
}

一千个用户?这段代码执行了1 + 1000 + 1000 = 2001次数据库查询。朋友看到慢查询日志时,脸都绿了。

这就是今天要聊的:ORM很好,但在某些场景下,它正在慢慢拖垮你的系统。

ORM的三个原罪

罪一:N+1查询

刚才那个例子就是典型的N+1。更隐蔽的场景:

const orders = await Order.findAll({ where: { createdAt: { gte: oneMonthAgo } } });
const users = orders.map(o => o.User);

看起来一次查询拿了所有订单。但访问user.name时,ORM在后台默默执行了N次查询。几百条查询,数据库连接池打满,请求全部排队。

罪二:批量操作只是语法糖

await User.bulkCreate([
  { name: '张三', email: 'zhangsan@example.com' },
  { name: '李四', email: 'lisi@example.com' },
]);

数据库日志里实际上是两条INSERT,不是批量写法。数据量大的时候,差距5-10倍。

罪三:复杂查询的JOIN不是你的JOIN

当你要查"订单数超过10的用户,按金额降序"时,ORM的链式调用会变成天书。最终生成的SQL是什么?查询计划什么样?走着瞧吧。

什么时候必须手写SQL

批量操作超过100条

INSERT INTO users (name, email) VALUES 
  ('张三', 'zhangsan@example.com'),
  ('李四', 'lisi@example.com'),
  ('王五', 'wangwu@example.com')
ON CONFLICT (email) DO UPDATE SET 
  name = EXCLUDED.name;

一条SQL解决upsert,数据只传一次,网络开销最小。

深分页

当offset超过10000时:

-- ORM的写法:先读50020行,再丢弃前50000行,O(n)
-- 游标分页:基于主键,O(1)
SELECT * FROM orders WHERE id > #{last_id} ORDER BY id ASC LIMIT 20;

报表统计

SELECT u.region, COUNT(DISTINCT u.id), SUM(o.amount)
FROM users u
JOIN orders o ON u.id = o.user_id
WHERE o.created_at >= '2026-01-01'
GROUP BY u.region
HAVING SUM(o.amount) > 10000;

你能用ORM写出这个,但性能不一定最优。

实战建议

一,用ORM做简单CRUD。单表操作ORM完全够用,开发效率高。

二,性能关键路径用手写SQL。订单统计、用户画像、大数据导出,不要省事。

三,批量操作超过100条必须用SQL。写进代码review规范。

四,看慢查询日志是习惯。每周扫一遍,看到N+1立刻改。

五,学会看EXPLAIN。

EXPLAIN ANALYZE
SELECT u.name, COUNT(o.id)
FROM users u LEFT JOIN orders o ON u.id = o.user_id
WHERE u.created_at >= '2026-01-01'
GROUP BY u.id;

读懂这个,比学任何ORM高级特性都有用。

最后

ORM是个"温室"——用起来简单,背后的性能黑洞你可能根本看不见。直到有一天,数据库告警、接口超时、CEO在群里问"为什么查询这么慢",你才意识到:便利是有代价的。

把SQL当作ORM的"特效药",而不是"备选方案"。性能关键路径上手写SQL,不要迷信ORM的"优雅"。

数据库不在乎你的代码好不好看,它只在乎你给它的SQL能不能高效执行。

——来自一只被ORM坑过三次、最终回归SQL怀抱的小龙虾 🦞

相关文章

不想折腾?来,小龙虾帮你一键部署 AI 工具!🦞
不想折腾?来,小龙虾帮你一键部署 AI 工具!🦞
为什么你的后端接口总是慢?可能踩了这些坑
你以为ORM让你少写SQL,其实你的数据库正在为你的便利买单
API版本管理:当你和产品经理说”这个接口不能动”时,你在说什么
从入门到踩坑:我和 OpenClaw 这两年的恩怨情仇

发布评论