2011-12-01 38 views
2

将可选1:1属性分解为各自独立的模型有什么优点和缺点?Rails ActiveRecord和DB规范化

例如,我正好遇到Rails代码是这样的:

class Dogs << ActiveRecord::Base 
    # :id (pk), :breed, :weight, :height, :tail_length 
end 

class DogSpotsInfo << ActiveRecord::Base 
    # :dog_id (pk), :spot_color, :avg_spot_size, :num_spots 
end 

但是,这是我会怎么做它(离开现场场NULL作为必要):

class Dogs << ActiveRecord::Base 
    # :id, :breed, :weight, :height, :tail_length, :spot_color, :avg_spot_size, :num_spots 
end 

在数据库级别,我相信唯一的区别是涉及可选属性的查询将需要另一个连接?

以前的方法还有其他的缺点吗?有没有优点?

编辑:

我想上一个巨大的狗表,其中说狗的20%,有斑点,也许一个亲前一种方法是更快顺序扫描,但我不是100%肯定的是,如果是那样的唯一的专家似乎是不成熟的优化。

我能想到的另一个功能是让模型更小巧整洁。但是,如果这是目标,也许你可以做到这一点,而不会影响数据库结构,通过类似has_spots :spot?这里最好的做法是什么?

+0

就我个人而言,我不是ActiveRecord的has_one关联类型的粉丝。只有一部分字段受到某些约束(例如,不兼容/不允许的列值组合)才有意义。人们不应该害怕数据库中的宽表,只要它们的索引正确。 – Toshio

回答

2

在一张表中包括所有记录可能是优先选择的方式。它以尺寸为代价为您提供更好的性能。

性能是有争议的,这取决于表的实际使用情况。如果系统昂贵的查询不需要点数据(如大量列表),那么它可能会更快,而不会让它们在桌面上,但如果您将数据保存在表上,则将查询调整为只提取所需数据会消除查询的成本几乎完全。

我已经看到1:1的实施,因为它对开发人员来说比任何逻辑差异代码更有意义。左外连接比内连接更昂贵,并且连接比没有连接更昂贵。

您可以通过不将这些信息保留在表上来减少整体数据库的大小,但对于大多数小型应用程序(低于1 TB),您应该优化性能。

我认为这样设置的唯一真实情况是理想的,如果你想限制用户可以选择的点的类型,或者如果你对狗的这些元素做了很多处理。

通过使用包含所有可能值的查找表,您可以获得相同的约束感,并且只允许用户从查找表中选择值。然后返回并在狗表中插入原始值。这确实具有可能污染狗表的不良后果,即数据没有被网页应用程序正确清理,但通过与现场查找表进行比较并纠正,可以快速地确定哪些数据不在约束范围内在网络应用程序中的问题。

+1

听起来很有趣。我可以问你在这个领域有多少经验(只是为了知道你背后的重量)? –

+1

我曾经和曾经为一家大型仓储公司工作过的人一起训练过。 (他们收集了几百太字节的关于人的信息。)我从他们身上获得了大部分表现偏差。我已经在空闲时间里清理了一些关于尺寸设计的Kimball书籍,它们一直是图案设计的唯一资源。重构查询最重要的是我最重要的一点。我已经与数据库工作了三年(我知道时间不长),但到目前为止,这是一个非常身临其境的体验。所以,我会拿一粒盐,但我仍然认为这是坚实的建议。 – jTC

2

当关系是“Is-A”类型而不是“Has-A”类型时,1:1关系经常被分解。在扩展的ER模型中,这被称为“专业化”。在SQL表的世界中,这有时会以“Class Table Inheritance”的名称出现。您可以查看这些条款中的任何一个,以获得相应主题的相当好的处理。

类表继承与“Single Table Inheritance”形成鲜明对比,后者导致带有NULLS的单个表在值不相关的位置出现。这看起来像你的选择狗和斑点。

在“汽车”的世界里,专业化可能是“车辆”,一个是“汽车”,一个是“卡车”。 (“卡车”在我的池塘旁边被称为“卡车”。)汽车和卡车是特殊类型的车辆。存储在卡车中而不存储在车辆中的属性是与不是卡车的车辆无关的属性。

目的一般不是为了提高性能,而是为了改进查询的形式。只有卡车数据的查询才能查询卡车表。仅关于车辆数据的查询只能查询车辆表。涉及车辆和卡车数据的查询可以查询将车辆和卡车连接到共同列上的视图。

与其他人所认为的相反,窄表的性能优于宽表,尽管与索引和连接相比效果较小。

您可以将Class Table Inheritance与名为“Shared Primary Key”的技术组合起来,您可以查看该技术。与使表格彼此相关的其他方式相比,您可以非常快速地进行连接,并且非常简单。共享主键在插入时涉及更多工作,因为您必须将常规值从通用表传播到程序控制下的相应专用表。

如果我正在做你的情况,我会寻找方法来利用你提到的各种燃料类型的专业化。有些查询可能最终只扫描五个专用表中的一个(即“子类表”),从而运行速度快五倍。

0

如果你有大量的数据库,前一种方法在任何一天都会更好,而后一种方法会更好。

在一个单独的表格中,我们不确定这个值是否会到来,这总是一个加分。如果只有20%的狗有斑点,那么它们不需要将它保存在同一个数据库表中,因为80%的列将会变黑,并且在从主表中检索数据时会出现大量数据将被挑选,这肯定会妨碍服务器的性能。如果数据库很小,那么也许可以不必制作第二张表格

如果我们担心连接的时间复杂性,那么我们可以应用索引,这将进一步降低我们的成本。

所以要点

1)如果数据库包含多条记录申请前者的技术再加上做一些索引,以节省服务器成本

2)如果数据库是小U可以去后者

去正常化
0

优点:

  • 每个表占用的内存,少表意味着更少的开销(有一次我正在处理数据库W¯¯ ith总共有100兆数据的30K表,并且数据库内存使用量很大)

  • 手动分析可以很容易完成,Ë出口1台到Excel,谷歌电子表格或任何你使用过滤器

缺点

  • 大量空值的列。

的另一种方法,以平衡许多列VS额外属性表的是使用串行化阵列对于不太常见的元件,如iPod互为作用,然后使用一个搜索服务器(elasticsearch,websolr等),其可使用全文处理查询...这将允许您在没有新列的情况下向Cars表添加新元素。像自驾车,自驾车一样。

+0

谢谢你的回答。好点 –