在大型、可扩展和易于维护的 Web 应用程序中,ORM 还是 SQL 更好?

4
我知道网络上已经有很多关于这个主题的帖子了。然而,许多人在谈论时倾向于关注不同的事情。我的主要目标是创建一个易于维护且可扩展的Web应用程序。相对于原始性能(或者我可以使用Java),我更加重视开发和维护速度。
这是因为我注意到当项目的代码规模增长时,你必须拥有可维护的代码。当我最初以过程化方式编写我的应用程序并没有使用任何框架时,仅仅一个月后它就变成了一场噩梦。我完全迷失在一堆意大利面条式的代码行中。我完全没有结构,尽管我非常努力地想实现它。
然后我意识到我必须有结构并正确编写代码。我开始使用CodeIgniter。这真的给了我结构和可维护的代码。许多用户说框架会减慢速度,但我认为他们误解了。代码必须是可维护和易于理解的。
框架+OOP+MVC使我的Web应用程序如此有结构,以至于添加功能不再是问题。
当我创建模型时,我倾向于认为它代表一个数据对象。也许是一个表单甚至是一个表/数据库。所以我想到了ORM(doctrine)。也许这将成为我的Web应用程序的又一个伟大实现,使其更具结构性,以便我可以专注于功能而不是重复自己。
然而,我以前从未使用过任何ORM,而且只学习了它的基础知识,知道为什么使用它很好等等。
所以现在我问所有像我一样追求可维护代码并知道它的重要性的人们,ORM(doctrine)是否像框架+MVC+OOP一样对于可维护的代码必不可少?
我想要更多的生活经验建议,而不是“原始SQL更快”的建议,因为如果我只关心原始性能,我应该在第一时间放弃框架+MVC+OOP,并继续生活在编码噩梦中。
感觉它非常适合MVC框架,其中模型是表格。
现在我有一个文件中有150个SQL查询,做一些简单的事情,例如按ID获取条目,按名称获取条目,按电子邮件获取条目,按X获取条目等等。我认为ORM可以减少这些行,否则我几乎可以肯定,这将在未来增长到1000个SQL行。如果我更改一个列,我必须更改所有列!再次想想都是噩梦。也许这还可以给我很好的符合MVC模式的模型。
ORM是否是实现结构化和可维护代码的正确方式?

2
你确定已经足够多次提到可维护性了吗?可能需要再加一些大写字母,否则人们可能无法理解你的重点。 - Matti Virkkunen
抱歉,刚从一场难以维护的代码噩梦中走出来。因此不知不觉地感到很有压力,这种情况发生了太多次:) - never_had_a_name
5个回答

6
很多用户认为框架会减慢速度,但我认为他们忽略了大局。代码必须易于维护和理解。
一个良好结构化、易于维护的系统如果性能不佳就毫无意义!
可维护性有益于构建应用程序的程序员。原始性能有益于真正使用应用程序进行工作(或其他任务)的人。那么,谁的关注点应该是最重要的:构建系统的人还是为此支付费用的人?
我知道事情并不像这样简单,因为客户最终将为一个结构不良的系统付费——可能会有更多的错误,肯定需要更长时间来修复它们,实现应用程序增强功能也需要更多的时间。通常情况下,一切都是权衡取舍。

1
完全同意。这正是问题的核心所在。开发人员似乎认为对他们来说拥有一个易于维护的系统(因为他们不熟悉原始SQL)比最终用户实际上拥有高性能的系统/体验更重要。这让人难以理解。 - Manachi

6

Ajsie,

我的建议是使用ORM。我使用NHibernate。虽然它不完美,但是学习曲线较大。但是通过ORM编写的代码更易于维护,更符合面向对象编程原则。如果你不使用ORM,就需要编写大量重复代码才能创建一个使用面向对象编程的应用程序,这几乎是不可能的。ORM可以消除大部分SQL代码。

另外一点是,如果你要构建一个面向对象系统,你最终还是需要编写自己的O/R Mapper。你需要调用动态SQL或存储过程,将数据作为reader或dataset获取,将其转换为对象,将对象之间的关系连接起来,将对象修改转换为sql插入/更新等等。你编写的代码会比NHibernate或市场上已经存在很长时间的其他ORM更慢且更容易出现错误。

你唯一的其他选择就是构建一个非常以数据为中心、过程式的应用程序。是的,在某些方面它可能运行得更快。我同意性能很重要。但是重要的是它足够快。如果你使用过程式代码来节省一些毫秒级别的时间,你的用户不会注意到性能的提高。但你会注意到烂代码。

在ORM中最大的性能瓶颈在于正确预取和惰性加载对象的方法。这会导致ORM的n-query问题。但是,这些问题很容易解决。你只需要对对象查询进行性能调整并限制对数据库的调用次数,告诉它何时使用连接等。NHibernate还支持丰富的缓存机制,因此有时根本不需要访问数据库。

我还不同意那些认为性能属于用户,而维护则属于开发人员的观点。如果你的代码不易于维护,它将变得没有可靠性,增加新功能时速度也很慢。你的用户会介意这一点。

我不会说每个应用程序都应该使用ORM,但我认为大多数应用程序会受益。另外,不要担心仅在必要时使用原生SQL或存储过程与ORM配合使用。如果你必须批量更新数百万条记录或编写非常复杂的报表(希望针对单独的、去规范化的报表数据库),那么直接使用SQL是最好的选择。使用ORM来处理面向对象编程、事务处理、业务逻辑以及CRUD操作,使用SQL来处理异常情况和边缘情况。

我建议阅读Jeffrey Palermo关于NHibernate和洋葱架构的文章。此外,参加他的敏捷开发课程或其他课程,了解O/R Mapping、NHibernate和面向对象编程。这就是我们使用的技术:NHibernate、MVC、TDD、依赖注入。


你说得太对了。我在使用MVC时,差点自己写了一个ORM!然后我想,“这不是ORM的功能吗”:)我想知道使用MVC的程序员是如何进行CRUD操作的?如果他们有一个名为“Users”的模型,那么他们只需添加一些用于CRUD的方法?对于所有列来说,这意味着很多SQL查询。我不使用.NET而是PHP。所以我想最好的选择应该是Doctrine,因为很多程序员都投票支持它。 - never_had_a_name

4

我像你一样开始开发,没有使用ORM工具。

然后我为那些软件开发更加产业化的公司工作,他们都使用某种ORM映射工具(功能多少不同)。开发更容易、更快速,能生成更易维护的代码等。

但我也看到了这些工具的缺点:非常慢。但那主要是工具(在那种情况下是Hibernate)的误用。

ORM工具是非常复杂的工具,因此很容易误用,但如果您有使用经验,您应该能够获得与原始SQL几乎相同的性能。我对您有三个建议:

  • 如果性能不是关键问题,请使用ORM工具(选择一个好的,我不用PHP开发,所以无法给您提供名称)
  • 确保对每个添加的功能检查ORM工具生成并发送到数据库的SQL(例如通过日志记录设施)。思考是否这是您编写查询时的方式。 ORM工具的大部分低效率来自于从数据库中收集的不需要的数据,将唯一请求拆分成多个请求等。缓慢很少是由工具本身引起的。
  • 不要将该工具用于所有事情。明智地选择何时不使用它(每次进行原始数据库访问都会降低可维护性),但有时,试图让ORM工具做一些它未开发的事情实际上并不值得尝试。

编辑:Orm工具对于非常复杂的模型非常有用:实体之间的许多关系。这在应用程序的配置部分或复杂的业务部分中经常遇到。因此,如果您只有很少几个实体,并且更改(重构)的机会较小,则其用处较小。

少数实体和众多实体之间的限制并不清晰。我会说50种不同类型(SQL表,没有连接表)以上就是许多,而不到10就是少数。

我不知道用于构建stackoverflow的工具是什么,但在之前必须经过非常仔细的性能测试。

如果您想构建一个将承受如此巨大负载的网站,并且如果您没有相关经验,请尝试在团队中找到已经处理过这类网站的人员(使用真实数据和代表性数量的并发用户进行性能测试并不是一项容易快速完成的任务)。拥有具有此方面经验的人将极大地加快该过程。


@thierry。ORM 不应该做哪些事情?和性能相比,是否会非常慢?如果我们谈论的是像 StackOverflow 这样的规模,那我在任何地方都不应该使用 ORM 吗? - never_had_a_name
1
作为一名开发者,我有17年的经验,并且参与了许多大型系统的开发。我可以确认,在任何大型/数据重的系统中,ORM比SQL慢数个数量级。 - Manachi
数量级(x100?)可能有点夸张了ORM的成本(如果你使用的ORM是这种情况,请更换另一个)。此外,您是否在说,当您通过ORM运行SQL查询时,它比如果您使用语言原语/标准库运行相同查询要慢数个数量级?用正确的工具做正确的事情。7年后,我仍然坚持认为到处编写原始SQL是过早优化。使用好的ORM工具,如果针对特定用例通过它生成的内容太慢,则转到该用例的SQL级别。 - Thierry

1

拥有高可维护性非常重要。我开发过大规模的 Web 应用程序,具有低级别的超高性能。最大的缺点是系统的维护,即开发新功能。如果你开发速度太慢,客户会寻找其他系统/应用程序...这是一个权衡。大多数 ORM 都有功能,如果需要直接对 SQL 进行优化查询。ORM 本身不是瓶颈。我认为更多的是关于良好的数据库设计。


0

我认为你忽略了实际情况。对于用户来说,性能是每天都需要关注的问题,他们并不在意可维护性。你正在表现出一种以自我为中心的态度,只关注个人利益,而不是那些为系统付费的人的利益。这不仅仅是为了你的方便。

也许你应该坐下来和用户一起观察他们使用你的系统一两天。然后你应该坐在一台与他们使用的电脑相同配置的PC上(不是开发机),并花一个星期的时间整天使用你的系统。这样你可能会理解他们的观点。


2
你在这里非常冒犯。我只是指出,如果你有可维护的代码,那么你就可以维护它 :) 如果你有很多开发人员,他们无法理解它,或者代码非常混乱(没有框架、面向对象编程、MVC),那么你不能轻松地添加/编辑/删除功能,应用程序也不如可能的好。我想知道ORM是否能给我带来这个优势。 - never_had_a_name
1
完全同意你的观点,ajsie。如果可维护性能够降低添加功能的成本,那么对于客户来说也是有好处的(他们将支付更少的费用)。因此,你在原始性能和代码可读性之间寻求平衡的做法完全是有道理的。 - Thierry
@thierry。感谢你理解我的观点,伙计。一个月后没有任何结构,我甚至无法理解自己的代码...这就是为什么我努力追求可维护性。 - never_had_a_name
1
你的态度会冒犯用户。系统的可维护性并不是首要的品质,可用性才是。 - HLGEM
@HLGEM:易用性和性能并不是同一回事。性能只需要达到“足够好”的水平就可以使用,但在易用性方面还有许多其他重要的因素,如果你把所有时间都花在低级细节上(如果没有一个体面的O/RM,你就必须这样做),那么你将无法花时间关注这些因素。 - BlueRaja - Danny Pflughoeft
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接