【问题标题】:Are there performance advantages by splitting a Django model/table into two models/tables?将 Django 模型/表拆分为两个模型/表是否有性能优势?
【发布时间】:2011-12-07 07:58:17
【问题描述】:

SO question 7531153 中,我询问了将 Django 模型一分为二的正确方法——使用 Django 的多表继承或显式定义 OneToOneField。

基于Luke Sneeringer's 评论,我很好奇将模型一分为二是否会带来性能提升。

我之所以考虑将模型一分为二,是因为我有一些字段将始终完成,而其他字段通常为空(直到项目关闭)。

将通常为空的字段(例如 actual_completion_dateactual_project_costs)放入 Django 中的单独模型/表中是否会提高性能?

分成两个模型

class Project(models.Model):
    project_number = models.SlugField(max_length=5, blank=False,
            primary_key=True)
    budgeted_costs = models.DecimalField(max_digits=10, decimal_places=2)
    submitted_on = models.DateField(auto_now_add=True)

class ProjectExtendedInformation(models.Model):
    project = models.OneToOneField(CapExProject, primary_key=True)
    actual_completion_date = models.DateField(blank=True, null=True)
    actual_project_costs = models.DecimalField(max_digits=10, decimal_places=2,
            blank=True, null=True)

【问题讨论】:

    标签: django database-design django-models database-schema


    【解决方案1】:

    事实上,恰恰相反。任何时候涉及多个表时,都需要 SQL JOIN,这对于数据库来说执行起来比简单的 SELECT 查询要慢。字段为空这一事实在性能方面毫无意义。

    根据表的大小和列数,只选择需要交互的字段子集可能会更快,但在 Django 中使用only 方法很容易:

    Project.objects.only('project_number', 'budgeted_costs', 'submitted_on')
    

    这会产生类似于:

    SELECT ('project_number', 'budgeted_costs', 'submitted_on') FROM yourapp_project;
    

    使用单独的模型(和表)仅出于模块化目的才有意义——例如您将Project 子类化以创建需要额外字段但仍需要通用Project 的所有字段的特定类型的项目.

    【讨论】:

    • 确实,唯一的优势是结构性(只要它有意义)。例如,如果扩展信息可以在多个项目之间共享,那么在模型中体现这种可能性就具有结构优势。不过,一对一的字段显然可以防止这种情况发生。
    • 你建议过早优化,IMO。
    • 我推荐了哪些“不成熟”的“优化”?
    • 您概括地说 JOIN 是不好的。在大多数情况下它们很糟糕,但有时很方便。
    • 我什么也没说。我说 JOIN 本质上比一个表上的简单 SELECT 慢。它是。期间,没有争论。慢多少以及这是否是一个问题是逐案确定的。不过,OPs 的问题是它是否会提高性能,而答案显然是否定的。它至少慢得可以忽略不计——当然不会更快。
    【解决方案2】:

    对于您的情况,如果某些信息仅在关闭时可用,我确实建议制作一个单独的模型。

    加入还不错。特别是在您的情况下,如果您在一个表中包含所有行而在另一个表中包含更少的行,则连接会更快。我经常使用数据库,在大多数情况下,判断连接是好是坏只是纯粹的猜测。在许多情况下,即使是全表扫描也比使用索引要好。您需要查看说明,如果性能是一个问题,并在可能的情况下分析 Db 工作(我知道 Oracle 支持这一点。)但在性能成为问题之前,我更喜欢更快的开发。

    我们在 Django 中有一个 5M 行的表。而且我们需要一个仅对 1K 行不为空的列。光是换桌子就得花半天时间。从头开始重建也需要几个小时。我们选择制作一个单独的模型。

    我参加了一场关于领域驱动设计的讲座,其中作者解释说,分离模型很重要,尤其是在开发新应用程序时,不要把所有东西都塞进一个类中。

    假设您有一个 CargoAircraft 类和 PassengerAircraft。将他们放在一个班级并“无缝”工作是如此诱人,不是吗?但是与它们的交互(计划、预订、重量或容量计算)完全不同

    因此,通过将所有内容放在一个类中,您会强迫自己在每个方法中使用一堆 IF 子句,在 Manager 中使用额外的方法,在更难的调试中使用更大的数据库表。基本上你让自己花更多时间开发是为了什么?只有两件事:1) 更少的连接 2) 更少的类名。

    如果你把类分开,事情就容易多了:

    • 干净的代码,没有丑陋的 if,没有 .getattr 和默认值
    • 轻松调试
    • 更多可维护的数据库

    因此,开发速度更快。

    【讨论】:

    • 显然,有意义的分离是好的。但是,在这种情况下,作者只是在划分模型,因为某些字段将是空白的。第二个模型只是第一个模型的“扩展信息”,是糟糕的设计。
    • 这可能是真的,但在这种情况下它们可以快速成长为更大的模型,我想告诉马修,DDD 是相当合理的,最好记住它。这部分是对您说 JOIN 不好的回应。
    • 假设您还没有阅读我对我的回答的评论,我会给您带来好处,但是让我重申一下,我从来没有说过 JOIN 是不好的。从来没有接近过这样说。
    • +1 表示“通过将所有内容放在一个类中,您会强迫自己在每个方法中使用一堆 IF 子句”
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-10-30
    • 1970-01-01
    • 1970-01-01
    • 2018-07-30
    • 1970-01-01
    • 1970-01-01
    • 2016-04-21
    相关资源
    最近更新 更多