Просмотр исходного кода

Replace distinct annotations with subqueries for much better performance

Jeremy Stretch 6 лет назад
Родитель
Сommit
ad4d23fa20
2 измененных файлов с 26 добавлено и 7 удалено
  1. 18 5
      netbox/dcim/api/views.py
  2. 8 2
      netbox/ipam/api/views.py

+ 18 - 5
netbox/dcim/api/views.py

@@ -1,7 +1,7 @@
 from collections import OrderedDict
 
 from django.conf import settings
-from django.db.models import Count, F
+from django.db.models import Count, F, OuterRef, Subquery
 from django.http import HttpResponseForbidden
 from django.shortcuts import get_object_or_404
 from drf_yasg import openapi
@@ -26,6 +26,7 @@ from extras.models import Graph, GRAPH_TYPE_INTERFACE, GRAPH_TYPE_SITE
 from utilities.api import (
     get_serializer_for_model, IsAuthenticatedOrLoginNotRequired, FieldChoicesViewSet, ModelViewSet, ServiceUnavailable,
 )
+from virtualization.models import VirtualMachine
 from . import serializers
 from .exceptions import MissingFilterException
 
@@ -280,9 +281,15 @@ class DeviceBayTemplateViewSet(ModelViewSet):
 #
 
 class DeviceRoleViewSet(ModelViewSet):
+    device_count = Device.objects.filter(
+        device_role=OuterRef('pk')
+    ).order_by().values('device_role').annotate(c=Count('*')).values('c')
+    virtualmachine_count = VirtualMachine.objects.filter(
+        role=OuterRef('pk')
+    ).order_by().values('role').annotate(c=Count('*')).values('c')
     queryset = DeviceRole.objects.annotate(
-        device_count=Count('devices', distinct=True),
-        virtualmachine_count=Count('virtual_machines', distinct=True)
+        device_count=Subquery(device_count),
+        virtualmachine_count=Subquery(virtualmachine_count)
     )
     serializer_class = serializers.DeviceRoleSerializer
     filterset_class = filters.DeviceRoleFilter
@@ -293,9 +300,15 @@ class DeviceRoleViewSet(ModelViewSet):
 #
 
 class PlatformViewSet(ModelViewSet):
+    device_count = Device.objects.filter(
+        platform=OuterRef('pk')
+    ).order_by().values('platform').annotate(c=Count('*')).values('c')
+    virtualmachine_count = VirtualMachine.objects.filter(
+        platform=OuterRef('pk')
+    ).order_by().values('platform').annotate(c=Count('*')).values('c')
     queryset = Platform.objects.annotate(
-        device_count=Count('devices', distinct=True),
-        virtualmachine_count=Count('virtual_machines', distinct=True)
+        device_count=Subquery(device_count),
+        virtualmachine_count=Subquery(virtualmachine_count)
     )
     serializer_class = serializers.PlatformSerializer
     filterset_class = filters.PlatformFilter

+ 8 - 2
netbox/ipam/api/views.py

@@ -66,9 +66,15 @@ class AggregateViewSet(CustomFieldModelViewSet):
 #
 
 class RoleViewSet(ModelViewSet):
+    prefix_count = Prefix.objects.filter(
+        role=OuterRef('pk')
+    ).order_by().values('role').annotate(c=Count('*')).values('c')
+    vlan_count = VLAN.objects.filter(
+        role=OuterRef('pk')
+    ).order_by().values('role').annotate(c=Count('*')).values('c')
     queryset = Role.objects.annotate(
-        prefix_count=Count('prefixes', distinct=True),
-        vlan_count=Count('vlans', distinct=True)
+        prefix_count=Subquery(prefix_count),
+        vlan_count=Subquery(vlan_count)
     )
     serializer_class = serializers.RoleSerializer
     filterset_class = filters.RoleFilter