2

I'm trying to use ViewSet to return list of all assets with the asset type name (instead of just id) but according to django-debug-toolbar, my queries are being duplicated leading to slower results.

1 Asset type can have multiple assets.

So, when I try to retrieve all assets (children) -- it's trying to fetch the asset type (parent) names for each of the assets (children) but it's running one query for every asset (child). Looks something like this: It's duplicated 6 times because I have 6 values in the Asset table currently.

QUERY = 'SELECT TOP 21 [mm_asset_type].[id], [mm_asset_type].[name], [mm_asset_type].[description] FROM [mm_asset_type] WHERE [mm_asset_type].[id] = %s' - PARAMS = (27,)
 6 similar queries.  Duplicated 3 times.        3.99    
Sel Expl
+   
QUERY = 'SELECT TOP 21 [mm_asset_type].[id], [mm_asset_type].[name], [mm_asset_type].[description] FROM [mm_asset_type] WHERE [mm_asset_type].[id] = %s' - PARAMS = (27,)
 6 similar queries.  Duplicated 3 times.        3.99    
Sel Expl
+   
QUERY = 'SELECT TOP 21 [mm_asset_type].[id], [mm_asset_type].[name], [mm_asset_type].[description] FROM [mm_asset_type] WHERE [mm_asset_type].[id] = %s' - PARAMS = (27,)
 6 similar queries.  Duplicated 3 times.        3.00    
Sel Expl
+   
QUERY = 'SELECT TOP 21 [mm_asset_type].[id], [mm_asset_type].[name], [mm_asset_type].[description] FROM [mm_asset_type] WHERE [mm_asset_type].[id] = %s' - PARAMS = (29,)
 6 similar queries.  Duplicated 3 times.        3.95    
Sel Expl
+   
QUERY = 'SELECT TOP 21 [mm_asset_type].[id], [mm_asset_type].[name], [mm_asset_type].[description] FROM [mm_asset_type] WHERE [mm_asset_type].[id] = %s' - PARAMS = (29,)
 6 similar queries.  Duplicated 3 times.        3.99    
Sel Expl
+   
QUERY = 'SELECT TOP 21 [mm_asset_type].[id], [mm_asset_type].[name], [mm_asset_type].[description] FROM [mm_asset_type] WHERE [mm_asset_type].[id] = %s' - PARAMS = (29,)
 6 similar queries.  Duplicated 3 times.

Expected Output

All I want is just a list of all the Assets along with the AssetType names -- is there a better way to do this?

Here are my models:

class AssetType(models.Model):
    id = models.AutoField(primary_key=True)
    name = models.CharField(max_length=80, unique=True)
    description = models.CharField(max_length=80)
    
    class Meta:
        db_table = "mm_asset_type"

class Asset(models.Model):
    asset_type = models.ForeignKey(AssetType, on_delete=models.CASCADE)
    asset_name = models.CharField(max_length=80)
    display_name = models.CharField(max_length=80)

    class Meta:
        db_table = "mm_asset_registry"

Here are my serializers:

class AssetTypeSerializer(serializers.ModelSerializer):
    class Meta:
        model = AssetType
        fields = "__all__"


class AssetSerializer(serializers.ModelSerializer):
    asset_type_name = serializers.CharField(source='asset_type.name')
    
    class Meta:
        model = Asset
        fields = ("id", "asset_type_name", "asset_name", "display_name")  

Finally, this is my ViewSet

class AssetViewSet(mixins.ListModelMixin,viewsets.GenericViewSet):
    queryset = Asset.objects.all()
    serializer_class = AssetSerializer

So, when I try to retrieve all assets -- it's trying to fetch the asset type names for each of the assets but it's running one query for every asset. Looks something like this:

QUERY = 'SELECT TOP 21 [mm_asset_type].[id], [mm_asset_type].[name], [mm_asset_type].[description] FROM [mm_asset_type] WHERE [mm_asset_type].[id] = %s' - PARAMS = (27,)
 6 similar queries.  Duplicated 3 times.        3.99    
Sel Expl
+   
QUERY = 'SELECT TOP 21 [mm_asset_type].[id], [mm_asset_type].[name], [mm_asset_type].[description] FROM [mm_asset_type] WHERE [mm_asset_type].[id] = %s' - PARAMS = (27,)
 6 similar queries.  Duplicated 3 times.        3.99    
Sel Expl
+   
QUERY = 'SELECT TOP 21 [mm_asset_type].[id], [mm_asset_type].[name], [mm_asset_type].[description] FROM [mm_asset_type] WHERE [mm_asset_type].[id] = %s' - PARAMS = (27,)
 6 similar queries.  Duplicated 3 times.        3.00    
Sel Expl
+   
QUERY = 'SELECT TOP 21 [mm_asset_type].[id], [mm_asset_type].[name], [mm_asset_type].[description] FROM [mm_asset_type] WHERE [mm_asset_type].[id] = %s' - PARAMS = (29,)
 6 similar queries.  Duplicated 3 times.        3.95    
Sel Expl
+   
QUERY = 'SELECT TOP 21 [mm_asset_type].[id], [mm_asset_type].[name], [mm_asset_type].[description] FROM [mm_asset_type] WHERE [mm_asset_type].[id] = %s' - PARAMS = (29,)
 6 similar queries.  Duplicated 3 times.        3.99    
Sel Expl
+   
QUERY = 'SELECT TOP 21 [mm_asset_type].[id], [mm_asset_type].[name], [mm_asset_type].[description] FROM [mm_asset_type] WHERE [mm_asset_type].[id] = %s' - PARAMS = (29,)
 6 similar queries.  Duplicated 3 times.

Expected Output

All I want is just a list of all the Assets (children) along with the AssetType (parent) names -- is there a better way to do this?

Thanks

Shubham Periwal
  • 2,198
  • 2
  • 8
  • 26

1 Answers1

2

You should use .select_related(…) [Django-doc] to fetch the types with the same query:

class AssetViewSet(mixins.ListModelMixin,viewsets.GenericViewSet):
    queryset = Asset.objects.select_related('asset_type')
    serializer_class = AssetSerializer

This will thus also fetch the asset_type fields in the same query as the one to fetch the Assets, and thus reduces the total number of queries to one.

Willem Van Onsem
  • 443,496
  • 30
  • 428
  • 555