over 8 years ago
用select_related来提取数据和不用select_related来提取数据的差别。
我有一个Model(用户每天会填写一些问题,这个Model用来收集用户每天填写的问题的答案):
class Answer(models.Model):
day_id = models.IntegerField()
set_id = models.IntegerField()
question_id = models.IntegerField()
answer = models.TextField(default='')
user = models.ForeignKey(User)
def __unicode__(self):
result = u'{4}:{0}.{1}.{2}: {3}'.format(self.day_id, self.set_id, self.question_id, self.answer, self.user.id)
return result
这个Model除了自带的Field外还有一个外键 user,用于引用Django自带的User表。
我需要将所有用户的每天的答案都输出到一个文件里, 所以首先要提取出所有的答案:
answers = Answer.objects.all()
for answer in answers:
print answer
运行这个指令会对数据库进行981次请求。数据库里有980行数据,Answer.objects.all()算是一次请求。那么剩下的980次请求是在干嘛呢?问题出在:
result = u'{4}:{0}.{1}.{2}: {3}'.format(self.day_id, self.set_id, self.question_id, self.answer, self.user.id)
当打印answer这个Object的时候,除了会打印出自身的Field外,还会打印出user.id. 由于Answer这个表中没有user.id这个Field,所以要单独请求User的表给出相应的id。这个就是造成980次请求的原因。每次打印一个answer,都要请求一遍User表来获取相对应的用户id。
这种提取数据的方式明显是不合理的,为了能一次完成任务,可以使用select_related:
answers = Answer.objects.all().select_related('user')
for answer in answers:
print answer
这样,数据库请求只有一次。select_related()的作用其实是把Answer和User这两张表给合并了:
SELECT ... FROM "answer" INNER JOIN "auth_user" ON ( "answer"."user_id" = "auth_user"."id" )
这样页面的载入时间就会被大大减少。