使用带有许多参数的select_related和prefetch_related

时间:2017-06-05 20:17:00

标签: python django django-views django-select-related

我对django比较新,我在django中使用 select_related() prefetch_related()来减少对数据库的点击。

这是我的 views.py 文件的一部分:

topic = Topic.objects.filter(id=topic_id).select_related('followed_by')
questions = Question.objects.filter(topics=topic).prefetch_related('answers','question_comments','answers__created_by__userprofile','answers__answer_comments')

如果没有select_related和prefetch_related,则视图会在23.36MS 中执行 42个查询,并且添加了这些查询后,它会在7.91MS 中减少到 10个查询,查看此数据,我认为这些功能非常棒。

所以我的问题是:使用这两个函数有什么缺点吗?我不能一次加入这么多桌子吗?

1 个答案:

答案 0 :(得分:1)

简单回答

不,没有缺点

真实答案

预取相关在python端进行连接。大部分时间这很好,但总是有个人资料。当您需要进一步调整数据库访问时,您可能还会发现Prefetch对象非常有用。

选择相关会执行您期望的操作(它创建连接语句并将其刷新到数据库),并且如果时间的话,它将表现得非常好。

在扩展中,连接可能变得更加阻碍 - 您可能希望通过非规范化,实现缓存层,按资源类型分离调用等来改变数据模型。

旁注

您希望开始将这些较大的查询放入您的模型管理器中,以便视图可以调用方法,您可以在幕后调整。

e.g。 (注意,有更新的方法可以使用queryset子类等。)

# models.py

class QuestionManager(models.Manager):
    def by_topic(self, topic):
        return self.filter(topic=topic).prefetch_related('...')

# views

def my_view(request, *args, **kwargs):
    # get the topic however
    topic = get_topic(kwargs.get('topic')
    Question.objects.by_topic(topic)