反向 Django 外键查找的复杂性
complexity of a reverse django foreign key lookup
假设我有这样一个模型:
class Post(models.Model):
name = models.CharField(max_length=25, unique=True)
class Picture(models.Model):
post = models.ForeignKey(to=Post, ondelete=models.CASCADE)
image = models.ImageField()
现在假设我做了这样的查询:
p = Post.objects.get(name=foo)
images = p.picture_set.all()
现在第一个查询显然会搜索所有帖子以获取名称为 foo
的帖子。
但我想知道第二个。它是搜索数据库中的所有 Picture
table 以查找所有具有 post=p
的图片,还是当我在第一个查询中获得 p
时可用的信息?
因为如果是前者,那么我担心可扩展性问题。
But I would like to know about the second one. Does it search through all the Picture table in the database to find all the pictures that have post=p or is the information available when I get p in the first query?
简答:默认情况下,ForeignKey
会添加一个索引,使得检索非常快(值的数量是对数的,反向记录的数量是线性的).
那要看数据库是否在ForeignKey
上建索引了。默认情况下,Django 会 构造一个索引。这意味着它不仅存储 table 的行,而且还存储允许快速查找具有特定值的所有行的数据结构。
索引的实现可以依赖于数据库。在 MySQL 中它会默认使用一个 BTREE
,这意味着对于一个值的查找,大约需要 O(log n) 来获取集合,以及 O(k) 和 k 使用该外键检索所有项目的数量。但是存在其他索引结构,例如某种 hashtable,它甚至允许(稍微)更快的查找,尽管 hashtable 例如检索具有 [=10 的所有元素的效率不高=] 小于给定的数字。
您还可以在其他列上添加索引,例如:
class Post(models.Model):
name = models.CharField(max_length=25<b>, db_index=True</b>, unique=True)
所以现在检索所有 Post
具有给定名称的对象,也会 运行 更快。
使用索引当然不是"free":这意味着每次插入或删除记录时,索引也需要更改(通常这也需要O(log n)).如果您通过更改外键的值来更新记录,那么该索引也需要更改。因此,索引提供了显着的加速,但应该只将索引放在经常执行查找的列上,否则 "maintaining" 索引的成本可能大于加快查找过程的收益。
假设我有这样一个模型:
class Post(models.Model):
name = models.CharField(max_length=25, unique=True)
class Picture(models.Model):
post = models.ForeignKey(to=Post, ondelete=models.CASCADE)
image = models.ImageField()
现在假设我做了这样的查询:
p = Post.objects.get(name=foo)
images = p.picture_set.all()
现在第一个查询显然会搜索所有帖子以获取名称为 foo
的帖子。
但我想知道第二个。它是搜索数据库中的所有 Picture
table 以查找所有具有 post=p
的图片,还是当我在第一个查询中获得 p
时可用的信息?
因为如果是前者,那么我担心可扩展性问题。
But I would like to know about the second one. Does it search through all the Picture table in the database to find all the pictures that have post=p or is the information available when I get p in the first query?
简答:默认情况下,ForeignKey
会添加一个索引,使得检索非常快(值的数量是对数的,反向记录的数量是线性的).
那要看数据库是否在ForeignKey
上建索引了。默认情况下,Django 会 构造一个索引。这意味着它不仅存储 table 的行,而且还存储允许快速查找具有特定值的所有行的数据结构。
索引的实现可以依赖于数据库。在 MySQL 中它会默认使用一个 BTREE
,这意味着对于一个值的查找,大约需要 O(log n) 来获取集合,以及 O(k) 和 k 使用该外键检索所有项目的数量。但是存在其他索引结构,例如某种 hashtable,它甚至允许(稍微)更快的查找,尽管 hashtable 例如检索具有 [=10 的所有元素的效率不高=] 小于给定的数字。
您还可以在其他列上添加索引,例如:
class Post(models.Model):
name = models.CharField(max_length=25<b>, db_index=True</b>, unique=True)
所以现在检索所有 Post
具有给定名称的对象,也会 运行 更快。
使用索引当然不是"free":这意味着每次插入或删除记录时,索引也需要更改(通常这也需要O(log n)).如果您通过更改外键的值来更新记录,那么该索引也需要更改。因此,索引提供了显着的加速,但应该只将索引放在经常执行查找的列上,否则 "maintaining" 索引的成本可能大于加快查找过程的收益。