Django的ORM有哪些限制?

21

我听说有些开发者不想使用ORM,但是并不知道为什么。ORM的缺点是什么?


1
对我来说,Django的ORM的一个很大的限制是它无法处理多个字段外键。 - Some programmer dude
1
@JoachimPileborg:“多字段外键”——根据一些人的说法——是一个设计错误,可以通过使用代理键轻松解决。更重要的是,最好将您的答案发布为答案,以便可以进行投票。 - S.Lott
1
它不支持复合主键,这是一个巨大的问题..除非架构非常简单或者你首先了解ORM的限制,否则不要使用它。我曾经遇到过重大的问题。 - Mario Aguilera
我在这里总结了一些观点,让我重新考虑Django作为一个整体:http://stackoverflow.com/q/18975376/781695 - user
6个回答

12

首先,我完全支持在大多数简单情况下使用ORM。当处理非常直观(关系型)数据模型时,它提供了很多方便。

但是,既然你问到了缺点...

从概念上讲,ORM永远不能有效地表示底层的数据模型。它将最多只是您数据的近似值 - 大多数情况下足以胜任。

问题在于ORM将基于"一个类->一个表"的映射方式,这种方式并不总是可行的。

如果您有非常复杂的数据模型 - 理想情况下,无法通过单个数据库表进行正确表示 - 那么您可能会发现,与其让ORM为您工作,您花费更多时间与之斗争。

实际上,您会发现总是有一些变通方法;一些开发人员会偏袒支持/反对ORM,但我倾向于采用混合方法。Django对此很好用,因为您可以根据需要轻松地切换到原始SQL。例如:

Model.objects.raw("SELECT ...")

ORM可以在99.99%的情况下,即在执行简单的CRUD操作时省去很多工作。

根据我的经验,完全避免使用ORM的两个最好理由是:

  • 当您有复杂的数据需要通过多个联接和聚合频繁检索时。通常,手写SQL会更清晰。
  • 性能。 ORM非常擅长构建优化查询,但是没有什么可以与编写高效的SQL代码相匹敌。

但说到底,在与Django广泛合作后,我可以用一只手数出ORM没有让我实现所需功能的次数。


使用Django,您可以创建代理模型,因此它不仅映射“一个类->一个表”。 - dan-klasson

10

5

以下是一位Django粉丝的回答:

  • 如果您使用继承并查询父类,则无法获取子类(而在SQLAlchemy中可以)。
  • Group ByHaving子句很难使用aggregate/annotate进行转换。
  • ORM生成的某些查询太长了,有时您会得到像model.id IN [1, 2, 3... ludicrous long list]这样的东西。
  • 有一种方法可以请求原始的“stuff is in field”条件,使用__contains,但没有“field is in stuff”的方式。由于没有跨DBMS执行此操作的便携式方法,因此为其编写原始SQL非常麻烦。如果您的应用程序开始变得复杂,则会出现许多这样的小边缘情况,因为正如@Gary Chambers所说,DBMS中的数据并不总是与OO模型匹配。
  • 它是一个抽象,有时抽象泄漏

但更多时候,我遇到的不想使用ORM的人是因为错误的原因:智力懒惰。有些人不愿意尝试某些东西,因为他们知道某些东西并想坚持使用它。在计算机科学领域,你会发现有很多这样的人,其中一大部分工作是跟上新技术。

当然,在某些领域中,这是有意义的。但通常有充分理由不使用ORM的人会在其他情况下使用ORM。我从未遇到过任何认真的计算机科学家说要全部使用ORM,只有一些人在某些情况下不使用它,并能够解释原因。

公平地说,许多程序员不是计算机科学家,他们是生物学家、数学家、教师或邻居Bob,他只是想提供帮助。从他们的角度来看,当您可以使用自己的工具箱做自己想做的事情时,不花费几个小时学习新东西是完全合理的。


2

每个对象关系映射系统似乎都存在各种问题,其中我认为 Ted Neward 的经典文章"计算机科学的越南战争"描述了这个主题。 (还有一篇针对该文章评论的跟进文章和 Stack Overflow 自己 Jeff Atwood 的一些评论在这里。)

此外,ORM系统的一个简单实际问题是它们使得很难看到给定代码运行了多少个查询(以及哪些查询),这显然会导致性能问题。在Django中,在您的单元测试中使用assertNumQueries断言确实有助于避免这种情况,使用django-devserver也可以,它是runserver的替代品,可以输出正在执行的查询。

0

其中一个最大的问题是将继承建立到Django ORM中很困难。这主要是因为(Django) ORM层试图通过同时具备关系和面向对象的特性来弥合差距。另外一个问题当然是多字段外键。

对Django ORM提出的一个指责是,它们抽象了数据库引擎的许多内容,使得使用它们编写高效、可扩展的应用程序变得不可能。对于某些类型的应用程序——那些有数百万次访问和高度相关的模型——这种说法通常是正确的。

绝大多数Web应用程序从未达到如此庞大的受众,并且没有达到那种复杂程度。Django ORM旨在快速启动项目,并帮助开发人员在不需要深入了解SQL的情况下进入基于数据库的项目。随着您的网站变得越来越大和受欢迎,您肯定需要像本文第一部分所述的那样审查性能。最终,您可能需要开始用原始SQL或存储过程(例如SQLAlchemy等)替换ORM驱动的代码。

令人高兴的是,Django的ORM功能不断发展。Django V1.1的聚合库是一个重大进步,它允许有效的查询生成,同时仍然提供熟悉的面向对象语法。为了获得更大的灵活性,Python开发人员还应该看看SQLAlchemy,特别是对于不依赖Django的Python Web应用程序。


0

在我看来,Django ORM 的一个更大的问题是缺乏复合主键,这使得我无法在 django.contrib.admin 中使用一些遗留数据库。

对于那些不需要 django.contrib.admin 的项目,我更喜欢 SqlAlchemy 而不是 Django ORM,我倾向于使用 Flask

Django 1.4 正在为 ORM 添加一些不错的“批处理”工具。


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