【问题标题】:Django: Number of ForeignKey Database QueriesDjango:外键数据库查询的数量
【发布时间】:2014-06-17 10:41:19
【问题描述】:

我想澄清一些事情,以便我可以通过 psycopg2 适配器优化我对 Postgres 的 Django ORM 查询。

假设我有三个模型:

from django.db import models   

class City(models.Model):
     #
     pass

class Person(models.Model):
     hometown = models.ForeignKey(City)

class Book(models.Model):
     author = models.ForeignKey(Person)

现在让我们进行以下查询:

book = Book.objects.get(pk = 4)

现在如果我想知道作者的原始 ID,我需要做的就是这个

>>> raw_id = book.author_id
>>> print raw_id
3

我的问题是, book.author_id 是否再次访问数据库,或者它只是从内存中获取它,因为它已经从 get 查询中获取了?据我了解,这个查询应该只有一次行程正确吗?

【问题讨论】:

    标签: sql django postgresql


    【解决方案1】:

    你是对的,book.author_id 不会再次访问数据库,外键 ID 存储在 book 中。如果您确实使用 DEBUG=True 设置进入 shell,您可以自行查看:

    >>> from django.db import connection
    
    >>> connection.queries
    []
    
    >>> book = Book.objects.get(pk=4)
    
    >>> connection.queries
    [{u'sql': u'SELECT "yourapp_book"."id", "yourapp_book"."author_id" FROM "yourapp_book" WHERE "yourapp_book"."id" = 4 ',
    u'time': u'0.003'}]
    
    >>> book.author_id
    7
    
    >>> connection.queries
    [{u'sql': u'SELECT "yourapp_book"."id", "yourapp_book"."author_id" FROM "yourapp_book" WHERE "yourapp_book"."id" = 4 ',
    u'time': u'0.003'}]
    
    >>> book.author
    <Author: Mark Twain>
    
    >>> connection.queries
    [{u'sql': u'SELECT "yourapp_book"."id", "yourapp_book"."author_id" FROM "yourapp_book" WHERE "yourapp_book"."id" = 4 ',
     u'time': u'0.003'},
     {u'sql': u'SELECT "yourapp_author"."id", "yourapp_author"."name" FROM "yourapp_author" WHERE "yourapp_author"."id" = 7 ',
     u'time': u'0.001'}]
    

    connection.queries 列出了在DEBUG 开启时通过 django shell 中的 ORM 发送的所有 SQL 查询。请注意,即使在执行 book.author_id 之后也只进行了一次查询,但是当我们执行 book.author 时进行了第二次查询,因为 django 必须返回数据库以获取要显示的作者姓名。

    您可以通过book = Book.objects.select_related('author').get(pk=4) 选择图书来避免第二次数据库查询。

    >>> connection.queries
    []
    
    >>> book = Book.objects.select_related('author').get(pk=4)
    
    >>> connection.queries
    [{u'sql': u'SELECT "yourapp_book"."id", "yourapp_book"."author_id", 
      "yourapp_author"."id", "yourapp_author"."name"
      FROM "yourapp_book" LEFT OUTER JOIN "yourapp_author" ON 
      ( "yourapp_book"."author_id" = "yourapp_author"."id" ) WHERE "yourapp_book"."id" = 4 ',
      u'time': u'0.003'}]
    
    >>> book.author
    <Author: Mark Twain>
    
    >>> connection.queries
    [{u'sql': u'SELECT "yourapp_book"."id", "yourapp_book"."author_id", 
      "yourapp_author"."id", "yourapp_author"."name"
      FROM "yourapp_book" LEFT OUTER JOIN "yourapp_author" ON 
      ( "yourapp_book"."author_id" = "yourapp_author"."id" ) WHERE "yourapp_book"."id" = 4 ',
      u'time': u'0.003'}]
    

    我还应该注意,对于在测试期间调试正在运行的 django 应用程序中实际进行的查询数量,django-debug-toolbar 工具是无价的。

    【讨论】:

    • 这非常有帮助,对于遇到此问题的所有其他读者,这一定会清除它!
    猜你喜欢
    • 1970-01-01
    • 2018-04-13
    • 2022-10-25
    • 1970-01-01
    • 2018-03-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多