django - 反向 django 外键查找的复杂性
问题描述
假设我有这样的模型:
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()
现在第一个查询显然会搜索所有帖子以获取具有 name 的帖子foo
。
但我想知道第二个。当我进入第一个查询时,它是否搜索Picture
数据库中的所有表以查找所有具有post=p
或可用信息的图片?
因为如果是前者,那么我担心可扩展性问题。p
解决方案
但我想知道第二个。它是否搜索数据库中的所有图片表以查找所有具有 post=p 的图片,或者当我在第一个查询中获得 p 时信息是否可用?
简短的回答:默认情况下 aForeignKey
添加一个索引,使检索非常快(值的数量是对数的,反向记录的数量是线性的)。
这取决于数据库是否在ForeignKey
. 默认情况下,Django将构建一个索引。这意味着它不仅存储表的行,而且还存储允许快速查找具有特定值的所有行的数据结构。
索引的实现可以依赖于数据库。在 MySQL 中,它默认使用 a BTREE
,这意味着对于一个值的查找,大约需要O(log n)来获取集合,并且O(k)与k具有该外键的项目数来检索所有. 但是存在其他索引结构,例如某种哈希表,甚至允许(稍微)更快的查找,尽管例如哈希表在检索ForeignKey
小于给定数字的所有元素时效率不高。
您还可以在其他列上添加索引,例如:
class Post(models.Model):
name = models.CharField(max_length=25, db_index=True, unique=True)
因此,现在检索Post
具有给定名称的所有对象也会运行得更快。
使用索引当然不是“免费的”:这意味着每次插入或删除记录时,索引也需要更改(通常这也需要O(log n))。如果您通过更改外键的值来更新记录,则该索引也需要更改。因此索引提供了显着的加速,但应该只将索引放在经常执行查找的列上,否则“维护”索引的成本可能大于加速查找过程的收益。
推荐阅读
- jenkins - 每次提交到 Github 后 Jenkins 构建触发器
- shake-build-system - 排除匹配的文件模式
- java - Java如何逐行读取文件并更改行的特定部分
- graphql - GraphQL 没有返回错误但未定义
- php - 503 服务在 PHP 进程上不可用
- https - 覆盖 Fiddler 证书的主题
- bixby - Mac 上的 Bixby Studio“更新失败”
- java - 休眠验证器导致多对多关系无法保存
- amazon-dynamodb - DyanmoDB 显示项目计数 = 0,未填充,并且在 Appsync 查询中不起作用
- javascript - 通过 javascript 在 HTML 中显示 JSON 字符串