Replace distinct annotations with subqueries for much better performance

This commit is contained in:
Jeremy Stretch 2019-04-12 17:18:04 -04:00
parent a46b43bff6
commit ad4d23fa20
2 changed files with 26 additions and 7 deletions

View File

@ -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

View File

@ -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