环境:
Django=="2.2"
Python=="3.6.8"
debug_toolbar=="1.11"
rest_framework=="3.8.2"
背景:
从基于函数的DRF端点切换到基于类的视图/视图集时,我发现基于类的视图在没有嵌套关系的情况下表现稍好,而在嵌套关系的情况下则差很多。
伪代码模型上下文:
Creator:
ForeignKey.Shipments[]
Unit:
ForeignKey.Shipments[]
Shipment:
ForeignKey.Addresses[]
ForeignKey.Creator
ForeignKey.Unit
Address:
Street
City
State
值得注意的序列化器上下文:
Unit:
Meta:
Depth = 1
Creator:
Meta:
Depth = Infinite
将上述结构的Viewset与等效的@apiview
进行比较时,我发现:
/addresses
在SQL查询计数(0.9x)上性能稍好,CPU开销为1.1倍(预期)/creators
在SQL查询计数(1.1x)上表现稍差,CPU开销为3.9x(预期)/creators/1
在SQL查询计数(0.9x)和3.4x CPU开销(意外)上的执行效果略好/creators/1
在SQL查询计数(3.3x)上的性能明显较差,而CPU开销却高达5.9x(意料之外)/units/1
具有可写的视图集,在SQL查询计数(4.4x)上表现非常差,CPU开销却高达7.9x(非常意外)prefetch_related
中的get_queryset
使用(非常意外)针对@apiview
的检索失败:
(240 queries including 235 similar and 120 duplicates)
针对viewsets.ReadOnlyModelViewSet
的检索失败:
(208 queries including 200 similar and 78 duplicates )
针对viewsets.ModelViewSet
的检索失败:
(803 queries including 801 similar and 801 duplicates )
所有这些似乎很不直观。
使用完全相同的序列化器的两种类型的端点如何有很大不同?
与基于函数的视图相比,Classviews和Viewsets似乎在涉及外键的情况下会导致 mass CPU和SQL性能下降,而我找不到真正的原因。
我希望N + 1个查询的执行效果很差,我不希望它们根据不同的DRF终结点样式为它们执行更多效果不佳。
为什么会发生这种情况?
答案 0 :(得分:0)
此处的统计信息用词不当,这是因为DRF可浏览API对端点接受的每种方法都执行了额外的请求。
相应地,如果您仅以1倍的参考速度执行GET @apiview
,则由于执行了3个附加请求,具有GET,PUT,PATCH,DELETE的端点的执行速度似乎会降低4倍。
当端点上有多个请求方法可用时,DRF的可浏览API掩盖了真实的速度/查询计数,为了查看端点的真实性能,您应该以编程方式请求它或使用?format=json
。
当我通过分析发现权限类被击中6次时,我发现了这一点:
答案 1 :(得分:-1)
看看这个答案Optimizing database queries in Django REST framework。 DRf不会自动优化您的查询,您仍然需要自己执行此操作。
如果您想进一步提高性能,请查看此应用https://github.com/K0Te/drf-serializer-cache