Django 如果列数过多,是否应将表除以OneToOneField?

Django 如果列数过多,是否应将表除以OneToOneField?,django,database-design,one-to-one,Django,Database Design,One To One,我有一个学生模型,已经有太多的领域,包括姓名,国籍,地址,语言,旅游历史等学生。详情如下: class Student(Model): user = OneToOneField(CustomUser, on_delete=CASCADE) # Too many other fields 我将更多信息存储在与学生模型有一对一关系的其他表中,例如: class StudentIelts(Model): student = OneToOneField(Student, o

我有一个学生模型,已经有太多的领域,包括姓名,国籍,地址,语言,旅游历史等学生。详情如下:

class Student(Model):
    user = OneToOneField(CustomUser, on_delete=CASCADE)
    #  Too many other fields
我将更多信息存储在与学生模型有一对一关系的其他表中,例如:

class StudentIelts(Model):

    student = OneToOneField(Student, on_delete=CASCADE)
    has_ielts = BooleanField(default=False,)
    # 8 other fields for IELTS including the scores and the date
    # and file field for uploading the IELTS result

# I have other models for Toefl, GMAT, GRE, etc that 
# are related to the student model in the same manner through 
# a OneToOne relationship such as:

class StudentIBT(Model):

    student = OneToOneField(Student, on_delete=CASCADE)
    has_ibt = BooleanField(default=False,)
    # other fields
我应该将这些表合并到一个表中,还是当前的数据库模式良好


我选择此模式的原因是,我不喜欢使用列太多的表。重点是,对于每个学生来说,应该有一个雅思和其他模式的表格,因此,例如,学生表格中的行数与雅思表格中的行数相同。

这是一个很难回答的问题,有很多不同的观点,但我想说你把你们的关系分成两种不同的模式是正确的

然而,有几个因素需要考虑

从数据库设计的角度来看,几乎没有理由拆分数据库表。每当有一对一的关系始终存在时,您应该将其合并到一个表中。列的数量无关紧要,除非您正在优化数据库

您可能希望以不同的方式对1:1关系的两个端点表进行集群或分区。 如果DBMS允许,您可能希望将它们放在不同的物理磁盘上,例如,SSD和其他磁盘上的性能更为关键 在廉价的硬盘上。 您已经测量了对缓存的影响,并且希望确保热列保留在缓存中,而不保留冷列 污染它。 您需要比整行更窄的并发行为,例如锁定。这是高度特定于DBMS的。 不同的列需要不同的安全性,但DBMS不支持列级权限。 触发器通常是特定于表的。理论上,您可以只使用一个表,并让触发器忽略错误的表的一半 在世界其他地区,一些数据库可能会对触发器的作用施加额外的限制 能做也不能做。例如,Oracle不允许您修改so 通过使用单独的 表,其中只有一个可能正在发生变异,因此您仍然可以修改 从你的触发器中选择其他方法,但还有其他方法可以解决 那个 数据库非常擅长处理数据,所以我不会拆分 该表仅用于更新性能,除非您已执行 基于代表性数据量的实际基准和结论 性能差异实际上是存在的,而且非常显著 e、 g.抵消增加的连接需求

Django的立场 如果您看看Django的设计方式,那么将表拆分为一对一关系有一些好处。在Django的生态系统中,这意味着独立的应用程序不必相互了解才能正常运行。在你的例子中,可以说学生模型不必知道任何关于雅思考试的事情,因为如果你把这两个分开,学生模型可以在其他应用程序中重用。 此外,一些对雅思考试进行某种分析的功能,不必“知道”参加这次考试的学生的任何情况


不过,一定要谨慎使用这种设计模式。问你自己一个好问题不一定是我的模型中有多少列?因为有时候一个模型中有很多数据是有理由的。因此,仅对这个问题回答“是”并不一定值得拆分您的表格。问自己一个更好的问题是,我想把这两类数据的责任/功能分开吗?这可能是出于任何原因,比如可重用性或安全性。

这是一个很难回答的问题,有很多不同的观点,但我想说你把你们的关系分成两种不同的模式是正确的

然而,有几个因素需要考虑

从数据库设计的角度来看,几乎没有理由拆分数据库表。每当有一对一的关系始终存在时,您应该将其合并到一个表中。列的数量无关紧要,除非您正在优化数据库

您可能希望以不同的方式对1:1关系的两个端点表进行集群或分区。 如果DBMS允许,您可能希望将它们放在不同的物理磁盘上,例如,SSD和其他磁盘上的性能更为关键 在廉价的硬盘上。 您已经测量了对缓存的影响,并且希望确保热列保留在缓存中,而不保留冷列 污染它。 您需要比整行更窄的并发行为,例如锁定。这是高度特定于DBMS的。 不同的列需要不同的安全性,但DBMS不支持列级权限。 触发器通常是特定于表的。理论上,您可以只使用一个表,并让触发器忽略错误的表的一半 在世界其他地区,一些数据库可能会对触发器的作用施加额外的限制 能做也不能做。例如,Oracle不允许您修改so 通过使用单独的 表,其中只有一个可能正在发生变异,因此您仍然可以修改 从你的触发器中选择其他方法,但还有其他方法可以解决 那个 数据库非常擅长处理数据,所以我不会拆分 该表仅用于更新性能,除非您已执行 基于代表性数据量的实际基准和结论 性能差异实际上是存在的,而且非常显著 e、 g.抵消增加的连接需求

Django的立场 如果您看看Django的设计方式,那么将表拆分为一对一关系有一些好处。在Django的生态系统中,这意味着独立的应用程序不必相互了解才能正常运行。在你的例子中,可以说学生模型不必知道任何关于雅思考试的事情,因为如果你把这两个分开,学生模型可以在其他应用程序中重用。 此外,一些对雅思考试进行某种分析的功能,不必“知道”参加这次考试的学生的任何情况


不过,一定要谨慎使用这种设计模式。问你自己一个好问题不一定是我的模型中有多少列?因为有时候一个模型中有很多数据是有理由的。因此,仅对这个问题回答“是”并不一定值得拆分您的表格。问自己一个更好的问题是,我是否想将这两种数据类型的责任/功能分开?这可能是出于任何原因,如可重用性或安全性。

StudentElts模型的单独责任是,我使用此模型创建一个modelform IeltsFormModelForm model=StudentElts。但是,如果两个模型合并,通过Model=Student并指定字段,这是可以实现的。然而,分割存在一个问题。学生第一次访问学生填写他/她的雅思的视图时,我需要这样做:``学生雅思,学生雅思创建=StudentElts.objects.get\u或学生创建=StudentElts.objects``那么,考虑到我解释的这些额外问题,你的建议是什么呢?我会说让他们分开,对学生和雅思使用两种不同的表格,只允许登录用户提交一份雅思表格,用form.save方法从当前登录用户处填写雅思学生。另一个提示:我认为雅思课程不应该被称为StudentIelts,但可能只是雅思,或类似于雅思成绩的东西,把它和一个学生联系起来的字段应该叫做学生。关于另一点,我同意你的看法。然而,我有另一个模型,程序。每个课程都有一个雅思成绩要求。模式应该是雅思考试,以区分它们。我甚至将这些字段命名为student_ielts_reading,以便在视图中区分它们每个学生可能都有一位老师。学生可以自己报名,也可以由老师报名。我不知道如何实施这一点。我应该定义一个不同的视图来插入和更新学生模型吗?我还应该保持这些分离吗?StudentElts模型的独立责任是我使用此模型创建一个modelform IeltsFormModelForm model=StudentElts。但是,如果两个模型合并,通过Model=Student并指定字段,这是可以实现的。然而,分割存在一个问题。学生第一次访问学生填写他/她的雅思的视图时,我需要这样做:``学生雅思,学生雅思创建=StudentElts.objects.get\u或学生创建=StudentElts.objects``那么,考虑到我解释的这些额外问题,你的建议是什么呢?我会说让他们分开,对学生和雅思使用两种不同的表格,只允许登录用户提交一份雅思表格,用form.save方法从当前登录用户处填写雅思学生。另一个提示:我认为雅思课程不应该被称为StudentIelts,但可能只是雅思,或类似于雅思成绩的东西,把它和一个学生联系起来的字段应该叫做学生。关于另一点,我同意你的看法。然而,我有另一个模型,程序。每个课程都有一个雅思成绩要求。模式应该是雅思考试,以区分它们。我甚至将这些字段命名为student_ielts_reading,以便在视图中区分它们每个学生可能都有一位老师。学生可以自己报名,也可以由老师报名。我不知道如何实施这一点。我应该定义一个不同的视图来插入和
更新学生模型?我应该把它们分开吗?我唯一想补充的是,你的考试模型可能共享了一些功能。考虑使用一个学生考试模型,这样你就可以将常见的行为封装在父类中,例如学生字段,也许是一个干净的方法或分数法。我想在学生模型创建的那一刻,即注册的那一刻,创建所有的学生模型。我觉得这样比较舒服。您建议使用我的注册表格的保存方法还是我的学生模型的保存方法。我对第二个更满意,因为学生模型可能是从非注册路线创建的。您是否建议向学生模型添加保存方法来执行此操作?无法回答此问题。两者都很好。还有你可以使用的post_save信号。这是一个偏好和业务需求的问题。使用post_save信号,我可以使其原子化吗?我的意思是,我担心我创建了一个学生模型,但是StudentExams模型没有被创建,我的应用程序崩溃,因为在视图中,我将依赖这样一个事实,即模型将首先被构建,如果在创建时失败,它将报告一个错误,这将是一个边缘案例。第二,在你看来,永远不要依赖这一点。在获取反向关系时,总是处理异常。我要补充的唯一一点是,您的考试模型可能共享一些功能。考虑使用一个学生考试模型,这样你就可以将常见的行为封装在父类中,例如学生字段,也许是一个干净的方法或分数法。我想在学生模型创建的那一刻,即注册的那一刻,创建所有的学生模型。我觉得这样比较舒服。您建议使用我的注册表格的保存方法还是我的学生模型的保存方法。我对第二个更满意,因为学生模型可能是从非注册路线创建的。您是否建议向学生模型添加保存方法来执行此操作?无法回答此问题。两者都很好。还有你可以使用的post_save信号。这是一个偏好和业务需求的问题。使用post_save信号,我可以使其原子化吗?我的意思是,我担心我创建了一个学生模型,但是StudentExams模型没有被创建,我的应用程序崩溃,因为在视图中,我将依赖这样一个事实,即模型将首先被构建,如果在创建时失败,它将报告一个错误,这将是一个边缘案例。第二,在你看来,永远不要依赖这一点。获取反向关系时,始终处理异常。