搜尋
首頁資料庫mysql教程为什么我说ORM是一种反模式

上周我在在上讨论了ORM,在那以后有人希望我澄清我的意思。事实上,我曾经写文章讨论过ORM,?但那是在一场关于SQL的大讨论的上下文中,我不应该把这将两件事情混为一谈。 因此,在本文中我将关注ORM本身。同时,我尽力保持简略,因为从我的SQL文章中显而易见

上周我在在上讨论了ORM,在那以后有人希望我澄清我的意思。事实上,我曾经写文章讨论过ORM,?但那是在一场关于SQL的大讨论的上下文中,我不应该把这将两件事情混为一谈。 因此,在本文中我将关注ORM本身。同时,我尽力保持简略,因为从我的SQL文章中显而易见的是:人们倾向于一旦读到让他们发怒的内容就会离开(同时留下一句留言,而不论他们所关注的东西是否在后面会讨论到)。

什么是反模式?

我很高兴地发现Wikipedia有一个相当全面的关于反模式的列表,包括来自编程界及其之外的内容。我之所以称ORM为反模式的原因是因为,反模式的作者定义了用来区分反模式和普通的坏习惯的两个条件,而ORM完全符合这些条件:

  1. 它开始的时候看起来很有用,但是从长期来看,坏处要大过好处
  2. 存在已验证并且可重复的替代方案

由于第一个因素导致了ORM令人抓狂(对我来说)的流行性:它第一眼看上去像是个好主意,但是当问题更加明显的时候,已经很难离开了。

这对ORM来说是什么意思?

我想说的主要问题在于?ActiveRecord,它由于 Ruby on Rails 而著名, 从那以后已经移植到了许多其他语言。然而,这些问题同样存在于其他的ORM层,比如Java的Hibernate和PHP的Doctrine。

ORM的优点

  • 简单:一些ORM层告诉你它们“消除了对SQL的要求”。我至今仍然看到这种承诺在传播。其他一些会更加现实地声称它们可以减少手写SQL的需要,但是仍然允许你在需要的时候使用它。对于简单的模型以及项目的早期,这确实是一个优点:使用ORM,无疑你能够更快地开始启动。然而,你将会走向错误的方向。
  • 代码生成:使用ORM从模型中消除用户层面的代码,这一做法开启了通向代码生成的大门。通过对schema的简单描述,“脚手架”模式可以为你的所有表生成一个可工作的界面。更加具有魔力的是,你可以修改你的schema描述,然后重新生成代码,从而消除了CRUD。同样,这在开始的时候确实是可行的。
  • 性能“足够好”:我没有看到任何ORM层声称在性能上更加优越。很明显,为了代码的敏捷性需要付出性能的代码。如果哪里变慢了,你总是可以用更加有效的手写SQL覆盖你的ORM方法。不是吗?

ORM的问题

1. 不充分的抽象

ORM最明显的问题是它并不能完全从实现细节中抽象出来。所有主流ORM的文档中到处都引用了SQL的概念。其中一些介绍的时候并不会表明其在SQL中的等价物,而其他一些则将库看作用来生成SQL的过程函数。

抽象的要点在于它应该使问题得以简化。对SQL进行抽象,同时又要求你懂得SQL,这使得你需要学习的东西成倍增加了:首先,你必须理解你正在试图执行的SQL是什么,然后你还要学习ORM的API,来让它为你编写这些SQL。在Hibernate中,为了完成复杂的SQL你甚至需要学第三种语言:HQL,它几乎就是SQL(但又不完全是),其在幕后被翻译成SQL。

ORM的支持者会辩解说并非每个项目都是如此,并非每个人都需要复杂的join,并且ORM是一个"80/20"解决方案,其中80%的用户只需要SQL中20%的功能,ORM可以处理这些问题。我能说的是,我15年来编写web应用的数据库后端的经历表明,事实并非如此。只有在项目刚开始的时候你不需要join和本地join。在那之后,你就要优化和巩固你的查询。即使80%的用户只用到SQL中30%的功能,可是100%的用户都需要打破ORM的抽象才能够完成工作。

2. 不正确的抽象

如果你的项目确实不需要任何关系数据功能,那么ORM可以非常完美地为你工作。但是接下来你又遇到另外一个问题:你用错了了数据存储。关系存储的额外付出是非常高的;这就是为什么NoSQL数据要快得多的重要原因之一。然而,如果你的数据是关系型的,那么额外的付出就是值得的:你的数据库不仅存储数据,它还表达了你的数据,并且可以基于关系概念回答关于它的问题,这比你用过程代码能够做到的要快速得多。

但是,如果你的数据不是关系型的,那么你就是在不适当的场合使用SQL,这为你增加了巨大且不必要的负担;为了让问题更加严重,你在其上又增加了一重额外的抽象。

另一方面,如果你的数据是关系型的,那么你的对象映射最终会失败。SQL是关于关系代数的:SQL的输出不是对象,而是对于某个问题的解答。如果你的对象“是一个”X的实例,并且“拥有一些”Y,且每个Y“属于”Z,那么对象在内存中正确的表达形式是什么? 它应该是X的属性,或者全部包含在Y中,或者/并且全部包含在Z中?如果你只得到X的属性,那么何时你运行查询来获得Y呢?而且,你是想要其中一个还是全部?现实中,答案是依赖于条件的:这就是为什么我说SQL是对于问题的回答。对象在内存中的表达形式取决于你的意图,然而面向对象设计没有依赖于上下文的表达这样的功能。关系不是对象;对象也不是关系。

3. 多个查询导致失败

这自然的引出了ORM的另一个问题:效率低下。当你获取一个时,你需要哪些属性?ORM并不知道,所以它总是取得全部(或者它要求你告诉它,但是这又打破了抽象)。开始的时候这不成问题,但是当你一次取出上千条纪录的时候,如果你只需要3个属性却不得不取出全部30列,这时就产生了严重的性能问题。许多ORM层非常不善于推断join,从而不得不使用分离的查询来获取关联数据。如前所述,许多ORM层明确声明效率将会有所牺牲,其中一些提供了某些机制来调整引起问题的查询。我从过去的经历中发现的问题表明,很少有只需要调整单个“银弹”查询的情况:应用的数据库后端之所以死掉不是因为其中某一条查询,而是众多的查询引起的。ORM缺少上下文敏感的性质意味着它无法巩固查询,相反必须借助cache或其他机制来进行一定程度的补偿。

那么替代方案是什么?

希望到这里我已经澄清ORM在设计上的一些缺陷。但是要作为一个反模式,还需要存在替代的解决办法。事实上有两个取代方法:

1. 使用对象

如果你的数据是对象,那么停止使用关系数据库。编程界当前正在出现键-值对存储的浪潮,它允许你以闪电般的速度访问优雅的、自我包含的海量数据。没有法律规定编写Web应用的第一步必须安装MySQL。对于对象的每一种表达方式都使用关系数据库是一种过度使用,这也是近几年SQL的名称不太好的原因之一。事实上,问题在于偷懒的设计。

2. 在模型中使用SQL

编程中作任何事情都只有一种正确的方式,这是一种危险的说法。然而根据我的实践,在面向对象的代码中表达关系模型的最佳方法仍然是模型层:将你的所有数据表示封装在一个单独的区域是一个好注意。然而,记住模型层的工作簿在于表达对象,而在于回答问题。提供一个可以回答你的应用程序所包含的问题的API,尽量保持简洁高效。有时候,这些回答显得格格不入,以致于看上去是“错误的”,甚至对于资深的OO开发者也是如此。但是,你可以根据经验来更好地找到其中的普遍性,从而允许你将多个查询方法重构为单个。

类似的,有时候输出会是单个对象X,它很容易表达。 但是也有时候输出是聚合的对象表格,或者单个整数值。你要忍住将这些内容用过多抽象来包装的诱惑,用对象自身的术语来描述。首要的是,不要相信OO能够表达任何对象和所有对象。OO本身是一种优美和灵活的抽象,但关系数据在其范围之外,把它不能表达的东西伪装成对象是ORM的核心与真正的问题。

总结

  • ORM最初比编写基于SQL的模型代码更快,也更容易理解
  • 它在任何项目早期都是足够有效的
  • 不幸的是,这些优点在项目复杂性提升的时候就消失了:抽象被打破,开发者被迫使用并理解SQL
  • 完全是非正式的声明,我认为ORM对抽象的破坏不是仅仅涉及20%的项目,而是几乎100%。
  • 对象并不足以充分表达关系查询的结果。
  • 关系查询映射到对象的不充分性导致了ORM后端应用的效率低下,这些问题普遍分布在应用的各处,并且除了完全放弃ORM之外,没有简单的解决办法。
  • 不要对任何问题都使用关系存储与ORM,而是更加仔细地思考你的设计
  • 如果你的数据天生就是对象,那么请使用对象存储("NoSQL")。它们要比关系数据库快得多。
  • 如果你的数据天生就是关系型的,那么关系数据库带来的开销是值得的。
  • 把你的关系查询封装在模型层中,设计你的API从而为应用提供数据访问支持;拒绝过分泛化的诱惑。
  • 面向对象无法以有效的形式表达关系数据;这是面向对象设计的一个基本限制,ORM无法修复它。
陳述
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
mysql:blob和其他無-SQL存儲,有什麼區別?mysql:blob和其他無-SQL存儲,有什麼區別?May 13, 2025 am 12:14 AM

mysql'sblobissuitableForStoringBinaryDataWithInareLationalDatabase,而ilenosqloptionslikemongodb,redis和calablesolutionsolutionsolutionsoluntionsoluntionsolundortionsolunsonstructureddata.blobobobissimplobisslowdeperformberbutslowderformandperformancewithlararengedata;

mySQL添加用戶:語法,選項和安全性最佳實踐mySQL添加用戶:語法,選項和安全性最佳實踐May 13, 2025 am 12:12 AM

toaddauserinmysql,使用:createUser'username'@'host'Indessify'password'; there'showtodoitsecurely:1)choosethehostcarecarefullytocon trolaccess.2)setResourcelimitswithoptionslikemax_queries_per_hour.3)usestrong,iniquepasswords.4)Enforcessl/tlsconnectionswith

MySQL:如何避免字符串數據類型常見錯誤?MySQL:如何避免字符串數據類型常見錯誤?May 13, 2025 am 12:09 AM

toAvoidCommonMistakeswithStringDatatatPesInMysQl,CloseStringTypenuances,chosethirtightType,andManageEngencodingAndCollat​​ionsEttingSefectery.1)usecharforfixed lengengtrings,varchar forvariable-varchar forbariaible length,andtext/blobforlargerdataa.2 seterters seterters seterters

mySQL:字符串數據類型和枚舉?mySQL:字符串數據類型和枚舉?May 13, 2025 am 12:05 AM

mysqloffersechar,varchar,text,and denumforstringdata.usecharforfixed Lengttrings,varcharerforvariable長度,文本forlarger文本,andenumforenforcingDataAntegrityWithaEtofValues。

mysql blob:如何優化斑點請求mysql blob:如何優化斑點請求May 13, 2025 am 12:03 AM

優化MySQLBLOB請求可以通過以下策略:1.減少BLOB查詢頻率,使用獨立請求或延遲加載;2.選擇合適的BLOB類型(如TINYBLOB);3.將BLOB數據分離到單獨表中;4.在應用層壓縮BLOB數據;5.對BLOB元數據建立索引。這些方法結合實際應用中的監控、緩存和數據分片,可以有效提升性能。

將用戶添加到MySQL:完整的教程將用戶添加到MySQL:完整的教程May 12, 2025 am 12:14 AM

掌握添加MySQL用戶的方法對於數據庫管理員和開發者至關重要,因為它確保數據庫的安全性和訪問控制。 1)使用CREATEUSER命令創建新用戶,2)通過GRANT命令分配權限,3)使用FLUSHPRIVILEGES確保權限生效,4)定期審計和清理用戶賬戶以維護性能和安全。

掌握mySQL字符串數據類型:varchar vs.文本與char掌握mySQL字符串數據類型:varchar vs.文本與charMay 12, 2025 am 12:12 AM

chosecharforfixed-lengthdata,varcharforvariable-lengthdata,andtextforlargetextfield.1)chariseffity forconsistent-lengthdatalikecodes.2)varcharsuitsvariable-lengthdatalikenames,ballancingflexibilitibility andperformance.3)

MySQL:字符串數據類型和索引:最佳實踐MySQL:字符串數據類型和索引:最佳實踐May 12, 2025 am 12:11 AM

在MySQL中處理字符串數據類型和索引的最佳實踐包括:1)選擇合適的字符串類型,如CHAR用於固定長度,VARCHAR用於可變長度,TEXT用於大文本;2)謹慎索引,避免過度索引,針對常用查詢創建索引;3)使用前綴索引和全文索引優化長字符串搜索;4)定期監控和優化索引,保持索引小巧高效。通過這些方法,可以在讀取和寫入性能之間取得平衡,提升數據庫效率。

See all articles

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

SecLists

SecLists

SecLists是最終安全測試人員的伙伴。它是一個包含各種類型清單的集合,這些清單在安全評估過程中經常使用,而且都在一個地方。 SecLists透過方便地提供安全測試人員可能需要的所有列表,幫助提高安全測試的效率和生產力。清單類型包括使用者名稱、密碼、URL、模糊測試有效載荷、敏感資料模式、Web shell等等。測試人員只需將此儲存庫拉到新的測試機上,他就可以存取所需的每種類型的清單。

SublimeText3 英文版

SublimeText3 英文版

推薦:為Win版本,支援程式碼提示!

Safe Exam Browser

Safe Exam Browser

Safe Exam Browser是一個安全的瀏覽器環境,安全地進行線上考試。該軟體將任何電腦變成一個安全的工作站。它控制對任何實用工具的訪問,並防止學生使用未經授權的資源。

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

Atom編輯器mac版下載

Atom編輯器mac版下載

最受歡迎的的開源編輯器