django 如何使用整数预取?

问题描述 投票:0回答:1

型号

class Challenge(models.Model):
    name = models.CharField(...)
    version = models.IntegerField(...)

class Workout(models.Model):
    name = models.CharField(...)
    version = models.IntegerField(...) # this field may not exist

# this is a through table
class ChallengeWorkoutRelation(models.Model):
    challenge_id = models.IntegerField() # for some reason, this is IntegerField, not ForeignKey
    workout_id = models.IntegerField() # for some reason, this is IntegerField, not ForeignKey
    version = models.IntegerField(default=0)

我想让所有锻炼都属于一项挑战:

for relation in ChallengeWorkoutRelation.objects.filter(challenge_id=challenge.pk, version=challenge.version):
    workout = Workout.objects.get(id=relation.workout_id)
    # do something with workout...
    
    # another version
    # workout = Workout.objects.get(id=relation.workout_id, version=challenge.version)

我可以优化这段代码以获得更高的性能吗?

django django-models django-orm
1个回答
0
投票

是的,您可以通过减少数据库查询次数来优化代码以提高性能。关键是尽量减少访问数据库的次数。在您的代码中,您当前正在为与挑战相关的每个锻炼进行单独的数据库查询,这可能会导致大量的数据库查询。

您可以使用 select_lated 或 prefetch_lated 查询集方法以更有效的方式检索相关对象以及 ChallengeWorkoutRelation 查询。在您的情况下,由于 ChallengeWorkoutRelation 具有 Challenge 和 Workout 的外键,因此您可以使用 select_lated 在单个查询中与 ChallengeWorkoutRelation 一起获取相关的 Workout 对象。

这是使用 select_lated 的优化版本:

relations =
ChallengeWorkoutRelation.objects.filter(challenge_id=challenge.pk,
version=challenge.version).select_related('workout')

for relation in relations:
    workout = relation.workout
    # do something with workout...

这样,您可以在单个查询中获取所有相关的 Workout 对象,而不是为每个关系进行单独的查询。

或者,如果您有大量关系,您可能需要考虑使用 prefetch_lated:

relations =
ChallengeWorkoutRelation.objects.filter(challenge_id=challenge.pk,
version=challenge.version).prefetch_related('workout')

for relation in relations:
    workout = relation.workout
    # do something with workout...

prefetch_lated 更适合处理反向外键关系或者有大量相关对象时。

根据您的具体用例和性能测试在 select_lated 和 prefetch_lated 之间进行选择。

© www.soinside.com 2019 - 2024. All rights reserved.