【问题标题】:making minimum SQL queries to get related objects进行最少的 SQL 查询以获取相关对象
【发布时间】:2013-01-18 20:54:51
【问题描述】:

我有一个方法定义如下:

def get_featured_books(cats=0):

"""  
This method would return a list of featured books
"""

fbooks = list()
categories = models.Category.objects.annotate( bookcount=Count('book')).order_by('bookcount')[:cats].reverse()    
for item in categories:
    fbooks.append(item.book_set.latest('posted_date'))
return fbooks

我在主页视图上使用上述方法显示精选书籍列表。在模板中,我使用以下标签:

{% for book in featured %}
    <h2>{{ book.title }}({{ book.category}})</h2>
    <span class="authors">{{book.authors.all|join:','}}</span>
{% endfor %}

但这整个概念引起了很多质疑。例如,如果我想展示 10 本精选书籍:

categories = models.Category.objects.annotate( bookcount=Count('book')).order_by('bookcount')[:cats].reverse()

将进行一次查询。

for item in categories:
        fbooks.append(item.book_set.latest('posted_date'))

将进行 10 次查询。

在模板中,{{ book.category}}{{ book.authors.all }} 将为每本书分别进行 1 次查询,因此在我的场景中,上述两个标签将进行 20 次查询。这使得它总共有 30 个查询(仅显示 10 条记录的列表)。当然,我将在主页上显示其他内容,这些内容会产生额外的查询。

问题是我怎样才能减少(最低)否。查询以获取上述信息。通常的做法是什么?

(PS:我知道缓存,我知道信息可以被缓存,但我在这里的目的是学习如何进行有效的查询。)

更新:

正如KrzysiekSzularz 建议的那样,我尝试如下使用select_relatedprefetch_related,但django 调试工具栏仍然显示它进行了32 个查询。

def get_featured_books(cats=0):

"""  
This method would return a list of featured books
"""

fbooks = list()
categories = models.Category.objects.select_related().annotate( bookcount=Count('book')).order_by('bookcount')[:cats].reverse()    
for item in categories:
    fbooks.append(item.book_set.prefetch_related('category').latest('posted_date'))
return fbooks

【问题讨论】:

  • select_related 用于categoryprefetch_related 用于authorsbook_set。您将得到 3 个查询。
  • @KrzysiekSzularz,感谢您的回复。我确实改用 select_relatedprefetch_related 但 DJDT 仍然显示 32 个查询,知道为什么吗?
  • 应用prefetch_related 后,您不能对查询进行任何修改。任何复制现有查询对象的操作都会中断预取。

标签: sql database django


【解决方案1】:

尽量减少查询数量的最佳方法是自己创建 SQL 语句并使用 SQLCommand 和 SQLDataAdapter 以老式方式执行它们。通过这种方式,您可以将所有数据堆叠到一个查询中,该查询会返回多个可用于不同视图的表。

更好的是——创建一个存储过程来返回所有需要的数据。 SQL Server 可以优化/保存存储过程的执行计划,使其更加高效。

如果您真的想坚持使用 LINQ,那么不幸的是,这可能无济于事。

【讨论】:

  • LINQ? SQL 服务器? @Amyth 是否甚至提到了 MS 工具?顺便提一句。您应该让 db 为您优化每个查询。使用存储过程只是一个丑陋的 hack。
猜你喜欢
  • 1970-01-01
  • 2022-12-02
  • 2016-06-01
  • 2015-11-09
  • 2022-01-07
  • 2013-04-26
  • 2016-07-11
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多