You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
@@ -36,6 +41,12 @@ retrieve the page can be customized by subclassing `PageNumberPagination` and
36
41
overriding the `page_query_param`. Page size can be controlled per request via
37
42
the `PAGINATE_BY_PARAM` query parameter (`page_size` by default).
38
43
44
+
#### Performance Testing
45
+
46
+
If you are trying to see if your viewsets are configured properly to optimize performance,
47
+
it is preferable to use `example.utils.BrowsableAPIRendererWithoutForms` instead of the default `BrowsableAPIRenderer`
48
+
to remove queries introduced by the forms themselves.
49
+
39
50
### Serializers
40
51
41
52
It is recommended to import the base serializer classes from this package
@@ -558,6 +569,43 @@ class QuestSerializer(serializers.ModelSerializer):
558
569
`included_resources` informs DJA of **what** you would like to include.
559
570
`included_serializers` tells DJA **how** you want to include it.
560
571
572
+
#### Performance improvements
573
+
574
+
Be aware that using included resources without any form of prefetching **WILL HURT PERFORMANCE** as it will introduce m*(n+1) queries.
575
+
576
+
A viewset helper was designed to allow for greater flexibility and it is automatically available when subclassing
577
+
`views.ModelViewSet`
578
+
```
579
+
# When MyViewSet is called with ?include=author it will dynamically prefetch author and author.bio
580
+
class MyViewSet(viewsets.ModelViewSet):
581
+
queryset = Book.objects.all()
582
+
prefetch_for_includes = {
583
+
'__all__': [],
584
+
'author': ['author', 'author__bio']
585
+
'category.section': ['category']
586
+
}
587
+
```
588
+
589
+
The special keyword `__all__` can be used to specify a prefetch which should be done regardless of the include, similar to making the prefetch yourself on the QuerySet.
590
+
591
+
Using the helper to prefetch, rather than attempting to minimise queries via select_related might give you better performance depending on the characteristics of your data and database.
592
+
593
+
For example:
594
+
595
+
If you have a single model, e.g. Book, which has four relations e.g. Author, Publisher, CopyrightHolder, Category.
596
+
597
+
To display 25 books and related models, you would need to either do:
598
+
599
+
a) 1 query via selected_related, e.g. SELECT * FROM books LEFT JOIN author LEFT JOIN publisher LEFT JOIN CopyrightHolder LEFT JOIN Category
600
+
601
+
b) 4 small queries via prefetch_related.
602
+
603
+
If you have 1M books, 50k authors, 10k categories, 10k copyrightholders
604
+
in the select_related scenario, you've just created a in-memory table
605
+
with 1e18 rows which will likely exhaust any available memory and
606
+
slow your database to crawl.
607
+
608
+
The prefetch_related case will issue 4 queries, but they will be small and fast queries.
0 commit comments