欢迎回来
登录你的知识库账户
忘记密码?
还没有账户?立即注册
创建账户
注册你的专属知识库
已有账户?去登录
找回密码
输入注册邮箱获取验证码
返回登录
请输入图片中的验证码以继续注册
加载中...
取消
新建收藏
手动添加你喜欢的内容
取消
编辑头像与昵称
上传新头像或修改你的显示昵称
支持 JPG/PNG,最大 2MB
取消

问题反馈

notebasewww.notebase.cn
控制台
内容库
动态
管理
账户
U
用户
--
在线
v0.8.7 · 知识库
笔记
KnowledgeBase
网络无边,知识有迹。
0笔记
0工具
30推荐

分类导航

按主题直达

编辑精选

站内用户贡献 · 真实笔记

最新收录

每日更新
继续浏览全部内容 →
>
笔记
0
加载中...
工具
0
此页用于记录用户反馈问题后的每一次改进
笔记用法

“写笔记”支持四种格式——Word 文档、Excel 表格、Markdown、纯文本,起稿或二次编辑时都能随时切换,同一篇笔记想用哪种形态来记,都由你说了算。

md、txt、csv、json 这类纯文本则原样载入,不做多余加工。拿一张现成的表倒进来、改几笔、再导出去,等于白用一台免费的格式转换器。

要带走就在右上角点“下载”,可导出 PDF、Word、Markdown、Excel、TXT 等格式;列表卡片“⋯”菜单里,也有同样的下载入口。

工具用法

在“工具”页点“+ 上传工具”即可发布:填好名称与链接,再用 Markdown 把使用方法写清楚——能解决什么问题、怎么装、怎么用,比堆介绍实在。

要分发安装包就一并上传压缩包(ZIP、RAR、7Z、TAR.GZ,最大 35MB),别人在详情页一键下载;只放链接不带附件也可以。

工具按大家的收藏热度排序,好用的自然会被顶上来。发布后可在详情页或卡片菜单里编辑、下架。

隐藏笔记

写笔记时勾上“隐藏”,这篇就只存在于你自己的账号里:不进列表、不进搜索、不上首页精选,也不会出现在任何公开的页面,链接发给别人同样打不开。

适合放密码、草稿、日记这类只给自己看的内容;想公开,去“发布”打开它,把“隐藏”的勾去掉再保存,之后编辑会默认保持原状态,不会悄悄变回公开。

数据安全

你的内容会同时保存在多个副本上,系统定期做备份与完整性校验,再配合异地容灾机制:就算某台机器出问题,数据也不会丢,可以长期放心存放;特别重要的资料,仍建议你另外再留一份备份。

技术

全站跑在容器化、模块化的现代架构上,更新、部署、回滚都很快,扩展性和稳定性都按长期运营的标准来设计(Built for reliability, designed to scale)。

理念

这个网站最早只是一个人的笔记仓库,后来慢慢长成现在的知识中枢。设计上很克制——没有广告、没有追踪、没有推荐算法,只是干干净净地存放一些东西;既然做好了,就公开出来,万一有人用得上呢。

原则

不做大而全,不做平台梦,保持简单、保持克制、保持好奇。所有内容都由用户贡献、由用户维护:不会突然冒出付费墙,不会在角落塞广告位,也不会把你的数据卖给第三方。

更多

产品会持续迭代,站内日志页记录着每一次改动,改了什么都有迹可循;想了解这个站是怎么一步步走到今天的,翻翻日志就能看到来龙去脉。

举报

如果在这里看到涉嫌违规的内容,点对应卡片右侧的“举报”按钮就能提交,我们会尽快核实处理;也谢谢你花一点时间,一起把这里维护干净。

趋势
// 点击导航加载发现
归档
// 归档为空
最近浏览
// 暂无浏览记录
发布
// 加载中...
用户发布
// 加载中...
用户管理
// 加载中...
访问统计
// 加载中...
内容审核
// 加载中...
个人信息
// 加载中...
返回首页

ORM 教会我的事:不如直接学 SQL

2026/7/5编程开发

ORM 看似简化数据库操作,实则引入诸多复杂性与性能问题,作者主张优先掌握 SQL 而非依赖 ORM。

背景与核心观点

作者在 30 个月中深度使用 SQLAlchemy(颇有好感)和 Hibernate(不喜),与 Postgres 及 SQLite 打交道,处理大量基于事件的“时间线”数据,并频繁生成报表。最终结论是:ORM 的弊大于利。它们可以作为辅助工具增强程序中的 SQL 操作,但绝不应取代 SQL。

对象/关系阻抗不匹配

关于“对象/关系阻抗不匹配”已有大量讨论,但亲身体验后才知其痛。Ted Neward 在其著名文章中列举了 ORM 沦为泥潭的多条理由。作者亲身经历了其中多个问题:实体标识问题、双模式问题、数据检索机制问题、部分对象问题。下文将逐一展开,并补充一个自己的观察。

部分对象、属性膨胀与外键

ORM 最具破坏性的问题之一是“属性膨胀”或“宽表”——即表不断累积属性。尽管作者尽量规避,有时仍不可避免(虽然 Postgres 的 hstore 能缓解)。例如,客户提供大量数据,要求根据业务逻辑附加到报表上,而你对其数据结构知之甚少,只能被动搬运。

这在数据库层面尚可接受,但在 ORM 中就成了痛点。问题尤其出现在直接使用实体构建查询时。例如项目初期 Hibernate 查询:

java
query(Foo.class).add(Restriction.eq("x", value))

当 Foo 只有 5 个属性时没问题,但属性增至 100 个时,该查询等价于 SELECT *,会返回大量不必要数据。ORM 鼓励这种用法,且常使编写精确投影(projection)变得和 SQL 一样繁琐。作者曾通过添加适当投影优化此类查询,将运行时间从分钟级降至秒级——所有时间都花在将数据库行转换为 Java 对象上。

另一个糟糕体验是外键的滥用。ORM 中类之间的链接在数据模型中表示为外键,若配置不当,检索对象时会触发大量 JOIN。作者工作中曾有一个表,使用推荐查询方法时,需访问 600 多个属性并执行 14 次 JOIN 才能获取单个对象。

属性膨胀与外键过度使用说明:要有效使用 ORM,仍然需要懂 SQL。作者认为,既然需要学 SQL,不如直接用 SQL,省去理解非 SQL 如何翻译成 SQL 的中间层。

数据检索:SQL 能力至关重要

当需要编写实际查询时,SQL 技能变得更为重要,尤其在效率敏感场景。作者观察,除非数据模型极其简单(从不 JOIN),否则你需要费尽心思让 ORM 生成高效的 SQL。多数情况下,ORM 生成的查询比直接 SQL 更晦涩。若保持查询简单,又不得不在应用层做大量数据库本可更快完成的工作。

窗口函数是相对高级的 SQL 特性,用 ORM 编写极为痛苦。若不将其纳入查询,意味着从数据库传输大量额外数据到应用。作者的做法是:使用模板系统编写查询,同时用 ORM 描述表结构。这样既享受应用层表描述便利,又直接使用 SQL,比任何其他方案都省事。

双模式危险

双模式问题几乎是不可避免的冗余:数据定义同时存在于数据库和应用中。若完全将定义放在应用层,则需用 ORM 代码编写 SQL DDL(数据定义语言),复杂度与用 ORM 编写高级查询相当。若将定义放在数据库,又需要应用层表示以方便使用并避免过多“字符串类型”。

作者更倾向将数据定义保留在数据库,再读入应用。这虽未解决问题,但使管理更可控。反射技术获取数据定义并不值得,作者最终接受了两处管理数据定义的冗余。

但迁移问题才是真正痛点:修改模型在应用中轻而易举,在数据库中却非常麻烦。数据库是持久化的,而应用数据不是。ORM 不仅不帮助管理数据迁移,反而碍手碍脚。作者的原则是:不应在应用中操作数据库的数据定义,而应操作查询结果。即,查询就是数据库的 API。因此,与其思考对象,不如思考带返回类型的函数。这引出一个问题:除了方便查询,ORM 是否还有存在价值?

标识问题

处理实体标识是使用 ORM 时必须时刻注意的事,迫使你为两个系统编写代码,却只拥有一个系统的表达能力。当有外键时,你用标识符引用相关实体。在应用中,“标识符”通常指内存地址(指针);在数据库中,指对象的状态。两者并不协调,因为数据库标识符只能在数据库中使用(数据的最终归宿)。这导致你需要手动刷新缓存或部分提交来获取数据库标识符。作者认为这甚至不能称为“泄漏抽象”,因为“泄漏”暗示只有少量内容逃逸,而这里问题严重得多。

事务:动态作用域与词法作用域的矛盾

Neward 提到开发者需要处理事务。事务是动态作用域的,这是一个强大但在编程语言中常被忽视的概念,因为过度使用会造成混乱。这导致大量带有异常处理的样板代码,并需仔细考虑事务边界。同时,你必须将会话对象传递给任何可能与数据库通信的函数或方法。

事务概念难以良好地映射到应用程序,因为它们依赖于基于时间的上下文。动态作用域是一种实现方式,但与主流的词法作用域范式冲突。因此,编写数据库相关代码时必须非常清楚事务的“时机”,这使模块化变得棘手(“这个有用的函数只在特定上下文中工作”)。

未来方向

作者开始质疑彻底拒绝存储过程的合理性。虽然听起来离经叛道,但对于作者的用例可能适用。毕竟,如果 ORM 的复杂性已经超过直接使用 SQL,那么存储过程或许是一条更务实的路径。

原文链接:https://wozniak.ca/blog/2014/08/03/1/index.html

编写使用方法
Markdown 格式 · Ctrl+Enter 确定
新建笔记
预览
数据表格
点击单元格编辑 · Tab 移动
A1fx
Sheet1
BIH1H2≡🔗</>
隐私提醒

取消
编辑工具
取消