Ade*_*laN 9 django django-orm django-rest-framework
我正在为我的API使用Django REST框架,昨天我想看看它如何适用于大数据.我找到了关于如何描述你的请求的教程(由Tom Christie编写),我发现对于10,000个用户,我的请求花费了惊人的2:20分钟.
大部分时间花在序列化对象上(大约65%),所以我想知道我该怎样做才能加快速度?
我的用户模型实际上扩展了默认的django模型,因此使用.values()不起作用,因为我也没有得到嵌套模型(即使它更快了).
任何帮助将不胜感激 :)
编辑
我在检索我的查询集时已经在使用.select_related(),它已经改善了我的时间,但只有几秒钟.总查询数是10,所以我的问题不在于数据库访问.
另外,我使用.defer(),以避免在此请求中不需要的字段.这也提供了一个小的改进,但还不够.
编辑#2
Models
from django.contrib.auth.models import User
from django.db.models import OneToOneField
from django.db.models import ForeignKey
from userena.models import UserenaLanguageBaseProfile
from django_extensions.db.fields import CreationDateTimeField
from django_extensions.db.fields import ModificationDateTimeField
from mycompany.models import MyCompany
class UserProfile(UserenaLanguageBaseProfile):
user = OneToOneField(User, related_name='user_profile')
company = ForeignKey(MyCompany)
created = CreationDateTimeField(_('created'))
modified = ModificationDateTimeField(_('modified'))
Run Code Online (Sandbox Code Playgroud)
Serializers
from django.contrib.auth.models import User
from rest_framework import serializers
from accounts.models import UserProfile
class UserSerializer(serializers.ModelSerializer):
last_login = serializers.ReadOnlyField()
date_joined = serializers.ReadOnlyField()
is_active = serializers.ReadOnlyField()
class Meta:
model = User
fields = (
'id',
'last_login',
'username',
'first_name',
'last_name',
'email',
'is_active',
'date_joined',
)
class UserProfileSerializer(serializers.ModelSerializer):
user = UserSerializer()
class Meta:
model = UserProfile
fields = (
'id',
'user',
'mugshot',
'language',
)
Run Code Online (Sandbox Code Playgroud)
Views
class UserProfileList(generics.GenericAPIView,
mixins.ListModelMixin,
mixins.CreateModelMixin):
serializer_class = UserProfileSerializer
permission_classes = (UserPermissions, )
def get_queryset(self):
company = self.request.user.user_profile.company
return UserProfile.objects.select_related().filter(company=company)
@etag(etag_func=UserListKeyConstructor())
def get(self, request, *args, **kwargs):
return self.list(request, *args, **kwargs)
Run Code Online (Sandbox Code Playgroud)
小智 14
ModelSerializers 很慢,你自己也说过。以下是有关发生这种情况的原因以及如何加快速度的更多信息: https: //hakibenita.com/django-rest-framework-slow
- 在性能关键端点中,使用“常规”序列化器,或者根本不使用。
- 不用于写入或验证的序列化器字段应该是只读的。
几乎总是性能问题来自N + 1个查询.这通常是因为您正在引用相关模型,并且生成每个对象的每个关系的单个查询以获取信息.您可以使用.select_related和.prefetch_related在您的get_queryset方法中改进这一点,如我的其他Stack Overflow答案中所述.
Django在数据库优化方面提供的相同提示也适用于Django REST框架,因此我建议您同时查看这些提示.
您在序列化期间看到性能问题的原因是因为这是Django对数据库进行查询的时间.
小智 5
我知道这已经过时了,你可能已经解决了你的问题......但对于其他任何人来说,这篇文章都是...
问题是你在做盲人
select_related()
Run Code Online (Sandbox Code Playgroud)
没有参数,这对您的查询绝对没有任何作用.你真正需要做的是
prefetch_related('user_profile')
Run Code Online (Sandbox Code Playgroud)
在没有深入细节的情况下,select_related用于"to one"关系,而prefetch_related用于"to many"关系.在您的情况下,您正在使用反向关系,这是一个"到很多"查询.
您的另一个问题是您没有正确使用反向关系.将序列化程序中的get_queryset()更改为此,我认为您将拥有所需的内容:
def get_queryset(self):
return UserProfile.objects.prefetch_related('user_profile').all()
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
7138 次 |
| 最近记录: |