进行最小的SQL查询以获取相关对象

时间:2013-02-04 07:15:37

标签: sql database django

我有一个定义如下的方法:

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

1 个答案:

答案 0 :(得分:0)

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

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

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