我有一个Post模型,一个Image模型和一个Channel模型。我在连接到Post模型的Image模型中有一个外键。此外,我试图添加连接到Channel模型的可为空的外键。
class Image(models.Model):
post = models.ForeignKey(Post, null=True, blank=True, on_delete=models.CASCADE)
comment = models.ForeignKey(Comment, null=True, blank=True, on_delete=models.CASCADE)
news = models.ForeignKey(News, null=True, blank=True, on_delete=models.CASCADE)
message = models.ForeignKey(Message, null=True, blank=True, on_delete=models.CASCADE)
channel = models.ForeignKey(Channel, null=True, blank=True, on_delete=models.CASCADE)
file = ProcessedImageField(upload_to='uploads/%Y/%m/%d/',
processors=[Transpose()],
format='JPEG',
options={'quality': 50},
blank=True)
我担心的是,频道字段几乎为空,因为每个频道只需要一张图片。但是图像必须与Post相关联。因此,每个频道都有一个与帖子相关的图片。但是,发布的帖子和图片将比频道多得多,因此Image模型中的频道字段将大部分时间被浪费。
我想到的另一个解决方案是专门为Channel模型创建一个新的图像模型,并在创建新的图像实例时,手动从原始的图像发布后连接的实例中复制图像。
class ChannelImage(models.Model):
channel = models.OneToOneField(Channel)
post = models.OneToOneField(Post)
file = ProcessedImageField(upload_to='uploads/%Y/%m/%d/',
processors=[Transpose()],
format='JPEG',
options={'quality': 50},
blank=True)
//copy a file from the original post
所以我的问题是,在模型中浪费这么多空null外键的代价是多少?在模型中有很多浪费的外键可以吗?
答案 0 :(得分:2)
拥有很多行中具有null值的属性的模型在技术上并没有什么坏处。
您谈论两种设计:
Image -> Channel ( image references channel )
ChannelImage -> Image ( new model to store channel image )
但是,在您的帖子中,您说:
因此,每个频道都有一个与帖子相关的图片。
但是,怎么了?
Channel -> Image ( channel reference image )
使用这种方法,您不会丢失任何信息,因为Image
仍与Post
连接。
我认为是这样的:
自django 2.2起,您可以编写index condition,这意味着,如果需要通过具有大量null的属性为模型建立索引,则可以根据需要仅对具有某些值的行进行索引此属性,例如不为null。
如果表很大,并且您的查询主要针对行的子集,则将索引限制为该子集可能很有用。将条件指定为Q。例如,condition = Q(pages__gt = 400)索引具有400页以上的记录。
答案 1 :(得分:0)
在考虑成本时,您需要考虑两个主要方面;时间和记忆。
关于Postgresql的外键成本有一个不错的post。在只有一个动态参数的情况下,执行了有关外键对时间性能的影响的测试。结果如下:
此函数接受的唯一参数是应创建的引用此源表的表数量。这些计时被收集了好几次,分别在三轮运行后平均为2961毫秒,3805毫秒,4606毫秒,5089毫秒和5785毫秒。我们可以看到,仅使用五个外键,我们的更新性能下降了28.5%。到我们有20个外键时,更新速度降低了95%!
考虑内存成本时,考虑到当今的计算机,这并没有多大关系。但是,如果您认为将有很多空的外键字段,则可以考虑创建一个交集表而不是使用外键。