【发布时间】:2015-12-30 09:32:03
【问题描述】:
这是演示我的问题的简化模型:
class User(models.Model):
username = models.CharField(max_length=30)
total_readers = models.IntegerField(default=0)
class Book(models.Model):
author = models.ForeignKey(User)
title = models.CharField(max_length=100)
class Reader(models.Model):
user = models.ForeignKey(User)
book = models.ForeignKey(Book)
所以,我们有Users、Books 和Readers(Users,他们读过Book)。因此,Reader 基本上是Book 和User 之间的多对多关系。
现在假设当前用户正在阅读一本书。现在,我想更新本书作者所有本书的读者总数:
# get the book (as an example pk=1)
book = Book.objects.get(pk=1)
# save Reader object for this user and this book
Reader(user=request.user, book=book).save()
# count and save the total number of readers for this author in all his books
book.author.total_readers = Reader.objects.filter(book__author=book.author).count()
book.author.save()
通过这样做,Django 为 PostgreSQL 创建了一个LEFT OUTER JOIN 查询,我们得到了预期的结果。但是,数据库表很大,这已经成为一个瓶颈。
在这个例子中,我们可以简单地将每个视图上的total_readers 增加一,而不是实际计算数据库行数。然而,这只是一个简化的模型结构,我们在现实中无法做到这一点。
我能做的是在 Reader 模型中创建另一个名为 book_author_id 的字段。因此,我对数据进行非规范化并且可以计算 Reader 对象,而无需 PostgreSQL 使用 User 表创建 LEFT OUTER JOIN。
最后,这是我的问题:是否可以创建某种数据库索引,以便 PostgreSQL 自动处理这种非规范化?还是我真的必须创建这个额外的模型字段并将作者的 PK 冗余存储在其中?
编辑 - 指出基本问题:我得到了几个很好的答案,它们适用于很多场景。但是,它们并没有解决这个实际问题。我唯一想知道的是,是否可以让 PostgreSQL 自动处理这种非规范化 - 例如通过创建某种数据库索引。
【问题讨论】:
标签: django database postgresql indexing denormalization