现在,我们需要将每日更新发送给我们最大的客户(<10%的客户).而且我需要存储发送给客户的最新更新的时间戳,所以下次我只会发送新的更新(我的意思是更新排序比TS大于存储的TS). 如果我向客户表添加了一个新列“LastUpdatesSentTS”,那么据我所知,它将符合规范化规则(如果没有,请给出证明它会断开规则化的链接). 但是,据我所知,从物理数据库设计的角度来看,最好创建一个包含2列[CustomerID,LastUpdatesSentTS]的新表,因为只有不到10%的客户将存储该TS信息.我的意思是,如果我将列添加到customers表中 – 大多数客户在该列中将为空.另外,如果我创建一个单独的新表,也许最好从客户表中删除布尔列“SendUpdates”(因为我将能够了解哪些客户需要通过将客户表加入新表来发送更新).此外,在这种情况下,我恐怕在几年内,我会有一堆非常小的表,当它们都可以在客户表中(没有我明白断开正常化). 简单来说,我看到2个可能的表设计: 1)
Table customers: [CustomerID,Name,...,SendUpdates,LastUpdatesSentTS]
2)
Table customers: [CustomerID,...] Table customer_updates_sending: [CustomerID,LastUpdatesSentTS]
你怎么看?
解决方法
原因是,正如您在您的问题中建议的,只有约10%的客户需要这些“更新”,因此,“客户”表中约有90%的记录将包含一个始终包含NULL值的字段,如果您将其作为同一客户表上的附加字段.将此实现为第二个表避免了此问题.
这不是一个真正的大问题,因为您的客户表非常小,但是在设计这样的事情时,我会考虑的更重要的问题是未来的发展.
基本上我可能会问自己:
“Would I,at any point in the future,
need to know about the customer’s
history of updates rather than just the very last one?”
根据应用情况(这听起来像是您所说的商业驱动程序),可能需要检查客户更新历史记录.思考管理信息,报告,年度摘要等)
在我写的几乎所有的业务应用程序中,我不得不保留几乎所有的东西至少几年(它通常被归档到数据仓库或单独的数据库)为了这些确切的目的.
即使您对客户的更新历史不感兴趣,我个人更喜欢采用2表格方式,因为它可以让历史记录保存,并提供更好的设计方法(因为客户表中只有一些记录需要记录第二个“更新”表).不过,请参阅以下我的EDIT以获取更多信息.如果我知道这些数据不需要历史记录,那么我将在现有客户的桌子上实现一个额外的领域.
另外,不要担心在数据库中有一堆非常小的表.通常可以有很好的理由拥有它们,并且是object-relational impedance mismatch的一部分,通常通过应用程序代码中更加“粘性”的面向对象设计来克服.
编辑:
(回应对我的回答的意见).
Aaron Bertrand使得一个非常有用的一点是,如果你有很多这样的附加数据的例子,就像这样,你每次连续使用一个单独的表,每次通过主键链接,你会得到很多非常小的表持有关于您单一客户的数据.在查询数据库以为甚至一个客户提取一整套数据时,这可能会因为许多表格过多而低效的JOINS而变得非常繁琐而且负担过重.
根据“附加”数据的性质,必须就如何实施数据做出务实的决定. Aaron建议,在“LastUpdate”日期字段的情况下,在90%的客户表中有很多NULL是没有坏处的,我在这里同意他的观点,从NULL的角度来看,不好的事情使用2表格方法的我自己的建议并不是基于删除NULL的愿望(尽管它完成了这一点),而是确保可以维护“LastUpdate”日期的历史.
当然,如果保留历史是完全不需要的(并且请记住,今天不需要什么,明天可能需要),将这个“LastUpdate”日期作为同一个“客户”表上的附加字段实施是不错的.事实上,如果一个客户和一个“最后更新”日期之间只有一个直接的一对一关系,那么将它分成两个表将是错误的.在这种情况下,我将其作为客户表上的附加字段实现,因为它现在是该客户的标量值.
当然,您可以随时将此作为客户表中的单个字段实现,如果它成为一个要求(假设一年下来),现在保留“最后更新”日期的历史记录,您可以随时重构数据库将其分解为第二张表格,但请记住,您只从这一点收集历史数据,因为您将没有上一年最后更新日期的记录.
如果您(或将)需要“最后更新”日期的历史记录(即客户记录与“最后更新”日期记录之间的一对多关系),则使用通过主键链接的第二表方法是您唯一的选择.