使用带有许多参数的 select_related 和 prefetch_related
using select_related and prefetch_related with many arguments
我对django比较陌生,我正在使用select_related()和prefetch_related() 在 Django 中减少我对数据库的访问。
这是我的 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.36 毫秒内执行 42 次查询,添加这些后,它减少到 7.91MS10次查询,看着这个数据,我觉得那些功能真的很棒
所以我的问题是:使用这两个函数有什么缺点吗?不应该一次性加入这么多桌吗?
简单回答
不,没有缺点
真实答案
预取相关在 python 端进行连接。大多数时候这很好,但总是配置文件。当您需要进一步调整数据库访问时,您可能还会发现 Prefetch
对象非常有用。
Select related 做你期望的事情(它创建连接语句并将其刷新到数据库)并且如果时间会表现得非常好。
在扩大规模时,联接可能会成为更大的障碍 - 您可能希望通过非规范化、实施缓存层、按资源类型分离调用等方式来改变数据模型。
旁注
您需要开始将这些更大的查询放入您的模型管理器中,这样视图就可以调用一个方法,而您可以在幕后调整。
例如(请注意,有更新的方法可以使用查询集子类等来执行此操作。)
# 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)
我对django比较陌生,我正在使用select_related()和prefetch_related() 在 Django 中减少我对数据库的访问。
这是我的 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.36 毫秒内执行 42 次查询,添加这些后,它减少到 7.91MS10次查询,看着这个数据,我觉得那些功能真的很棒
所以我的问题是:使用这两个函数有什么缺点吗?不应该一次性加入这么多桌吗?
简单回答
不,没有缺点
真实答案
预取相关在 python 端进行连接。大多数时候这很好,但总是配置文件。当您需要进一步调整数据库访问时,您可能还会发现 Prefetch
对象非常有用。
Select related 做你期望的事情(它创建连接语句并将其刷新到数据库)并且如果时间会表现得非常好。
在扩大规模时,联接可能会成为更大的障碍 - 您可能希望通过非规范化、实施缓存层、按资源类型分离调用等方式来改变数据模型。
旁注
您需要开始将这些更大的查询放入您的模型管理器中,这样视图就可以调用一个方法,而您可以在幕后调整。
例如(请注意,有更新的方法可以使用查询集子类等来执行此操作。)
# 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)