幕后的 Django 查询集
Django queryset behind the scenes
**
为一致性和连接创建外键的区别
**
我可以在 Django 中使用外键和查询集 API。
我只是想更深入地了解它是如何在幕后工作的。
在 Django 手册中,它说
a database index is automatically created on the ForeignKey. You can
disable this by setting db_index to False. You may want to avoid the
overhead of an index if you are creating a foreign key for consistency
rather than joins, or if you will be creating an alternative index
like a partial of multiple column index.
为一致性而不是连接创建外键
这部分让我很困惑。
如果您像下面这样使用外键进行查询,我希望您使用 Join 关键字。
SELECT
*
FROM
vehicles
INNER JOIN users ON vehicles.car_owner = users.user_id
例如,
class Place(models.Model):
name = models.Charfield(max_length=50)
address = models.Charfield(max_length=50)
class Comment(models.Model):
place = models.ForeignKeyField(Place)
content = models.Charfield(max_length=50)
如果您使用像 Comment.objects.filter(place=1)
这样的查询集,我希望在低级别 SQL 命令中使用 Join 关键字。
但是,当我通过在控制台中打印 queryset.query 来检查它时,它显示如下。
(我用模型简化只是为了解释。下面,它显示了我模型中的所有属性。您可以忽略属性)
SELECT
"bfm_comment"."id", "bfm_comment"."content", "bfm_comment"."user_id", "bfm_comment"."place_id", "bfm_comment"."created_at"
FROM "bfm_comment" WHERE "bfm_comment"."place_id" = 1
为一致性创建外键与为连接创建外键
简单地说,我想如果你使用任何查询集,就意味着使用外键进行连接。因为你可以很容易地通过c = Comment.objects.get(id=1) c.place.name
得到parent的table数据。我认为它在幕后加入了两个 table。但是 Print(queryset.query)
的结果不是 Join Keyword 而是 Find it by Where keyword.
我从回答中理解的方式
案例一:
Comment.objects.filter(place=1)
结果
SELECT
"bfm_comment"."id", "bfm_comment"."content", "bfm_comment"."user_id", "bfm_comment"."place_id", "bfm_comment"."created_at"
FROM "bfm_comment"
WHERE "bfm_comment"."id" = 1
案例二:
Comment.objects.filter(place__name="df")
结果
SELECT "bfm_comment"."id", "bfm_comment"."content", "bfm_comment"."user_id", "bfm_comment"."place_id", "bfm_comment"."created_at"
FROM "bfm_comment" INNER JOIN "bfm_place" ON ("bfm_comment"."place_id" = "bfm_place"."id")
WHERE "bfm_place"."name" = df
案例 1 正在搜索 comment.id 列在评论 table 中为 1 的行。
但是在情况2中,它需要知道Place table的属性'name',所以它必须使用JOIN关键字来检查Place [=]列中的值94=]。 对吗?
因此,如果我使用像 Case2 这样的查询集,并且最好在外键上创建索引,是否可以认为我为连接创建了一个外键?
对于上面的问题,我想我可以从Django Manual
那里得到答案
Consider adding indexes to fields that you frequently query using
filter(), exclude(), order_by(), etc. as indexes may help to speed up
lookups. Note that determining the best indexes is a complex
database-dependent topic that will depend on your particular
application. The overhead of maintaining an index may outweigh any
gains in query speed
总之,这实际上取决于我的应用程序如何使用它。
执行下面的命令就可以揭开谜底了
./manage.py sqlmigrate myapp 0001
注意将 myapp
替换为您的应用程序名称(bfm
我认为)并将 0001 替换为创建 Comment 模型的实际迁移。
生成的 sql 将显示实际的 table 是用 place_id int
创建的,而不是 place Place
,这是因为 RDBMS 对模型一无所知,模型仅在应用程序级别。 django orm 的工作是从 RDBMS 中获取数据并将它们转换为模型实例。这就是为什么您总是在每个 Comment
实例中获得一个 place
成员,并且该 place
成员使您可以依次访问相关 Place
实例的成员。
那么当你这样做时会发生什么?
Comment.objects.filter(place=1)
Django 足够聪明,知道您指的是 place_id,因为 1 显然不是 Place
的实例。但是,如果您使用 Place 实例,结果将是相同的。所以这里没有join。上面的查询肯定会受益于 place_id 上的索引,但它不会受益于外键约束!!仅查询 Comment table。
如果你想加入,试试这个:
Comment.objects.filter(place__name='my home')
具有 __
的这种性质的查询通常会导致联接,但有时会导致子查询。
查询集是惰性的。
https://docs.djangoproject.com/en/1.10/topics/db/queries/#querysets-are-lazy
QuerySets are lazy – the act of creating a QuerySet doesn’t involve
any database activity. You can stack filters together all day long,
and Django won’t actually run the query until the QuerySet is
evaluated. Take a look at this example:
**
为一致性和连接创建外键的区别
**
我可以在 Django 中使用外键和查询集 API。
我只是想更深入地了解它是如何在幕后工作的。
在 Django 手册中,它说
a database index is automatically created on the ForeignKey. You can disable this by setting db_index to False. You may want to avoid the overhead of an index if you are creating a foreign key for consistency rather than joins, or if you will be creating an alternative index like a partial of multiple column index.
为一致性而不是连接创建外键
这部分让我很困惑。
如果您像下面这样使用外键进行查询,我希望您使用 Join 关键字。
SELECT
*
FROM
vehicles
INNER JOIN users ON vehicles.car_owner = users.user_id
例如,
class Place(models.Model):
name = models.Charfield(max_length=50)
address = models.Charfield(max_length=50)
class Comment(models.Model):
place = models.ForeignKeyField(Place)
content = models.Charfield(max_length=50)
如果您使用像 Comment.objects.filter(place=1)
这样的查询集,我希望在低级别 SQL 命令中使用 Join 关键字。
但是,当我通过在控制台中打印 queryset.query 来检查它时,它显示如下。
(我用模型简化只是为了解释。下面,它显示了我模型中的所有属性。您可以忽略属性)
SELECT
"bfm_comment"."id", "bfm_comment"."content", "bfm_comment"."user_id", "bfm_comment"."place_id", "bfm_comment"."created_at"
FROM "bfm_comment" WHERE "bfm_comment"."place_id" = 1
为一致性创建外键与为连接创建外键
简单地说,我想如果你使用任何查询集,就意味着使用外键进行连接。因为你可以很容易地通过c = Comment.objects.get(id=1) c.place.name
得到parent的table数据。我认为它在幕后加入了两个 table。但是 Print(queryset.query)
的结果不是 Join Keyword 而是 Find it by Where keyword.
我从回答中理解的方式
案例一:
Comment.objects.filter(place=1)
结果
SELECT
"bfm_comment"."id", "bfm_comment"."content", "bfm_comment"."user_id", "bfm_comment"."place_id", "bfm_comment"."created_at"
FROM "bfm_comment"
WHERE "bfm_comment"."id" = 1
案例二:
Comment.objects.filter(place__name="df")
结果
SELECT "bfm_comment"."id", "bfm_comment"."content", "bfm_comment"."user_id", "bfm_comment"."place_id", "bfm_comment"."created_at"
FROM "bfm_comment" INNER JOIN "bfm_place" ON ("bfm_comment"."place_id" = "bfm_place"."id")
WHERE "bfm_place"."name" = df
案例 1 正在搜索 comment.id 列在评论 table 中为 1 的行。 但是在情况2中,它需要知道Place table的属性'name',所以它必须使用JOIN关键字来检查Place [=]列中的值94=]。 对吗?
因此,如果我使用像 Case2 这样的查询集,并且最好在外键上创建索引,是否可以认为我为连接创建了一个外键?
对于上面的问题,我想我可以从Django Manual
那里得到答案Consider adding indexes to fields that you frequently query using filter(), exclude(), order_by(), etc. as indexes may help to speed up lookups. Note that determining the best indexes is a complex database-dependent topic that will depend on your particular application. The overhead of maintaining an index may outweigh any gains in query speed
总之,这实际上取决于我的应用程序如何使用它。
执行下面的命令就可以揭开谜底了
./manage.py sqlmigrate myapp 0001
注意将 myapp
替换为您的应用程序名称(bfm
我认为)并将 0001 替换为创建 Comment 模型的实际迁移。
生成的 sql 将显示实际的 table 是用 place_id int
创建的,而不是 place Place
,这是因为 RDBMS 对模型一无所知,模型仅在应用程序级别。 django orm 的工作是从 RDBMS 中获取数据并将它们转换为模型实例。这就是为什么您总是在每个 Comment
实例中获得一个 place
成员,并且该 place
成员使您可以依次访问相关 Place
实例的成员。
那么当你这样做时会发生什么?
Comment.objects.filter(place=1)
Django 足够聪明,知道您指的是 place_id,因为 1 显然不是 Place
的实例。但是,如果您使用 Place 实例,结果将是相同的。所以这里没有join。上面的查询肯定会受益于 place_id 上的索引,但它不会受益于外键约束!!仅查询 Comment table。
如果你想加入,试试这个:
Comment.objects.filter(place__name='my home')
具有 __
的这种性质的查询通常会导致联接,但有时会导致子查询。
查询集是惰性的。
https://docs.djangoproject.com/en/1.10/topics/db/queries/#querysets-are-lazy
QuerySets are lazy – the act of creating a QuerySet doesn’t involve any database activity. You can stack filters together all day long, and Django won’t actually run the query until the QuerySet is evaluated. Take a look at this example: