I have a complicated report in Django, which is written as raw SQL, and than stored in the database as a database view.
I have a Django model (managed=False), tied to that database view, so that I can utilize the django ORM and django rest framework, on top of the database view. This practice is something that I have used on several projects, and works fine.
For one specific report, I found that I need to meddle with the postgres query planner, to get it running faster. Before each SELECT statement on that model (database view), to get the SQL to run faster, I need to do:
SET enable_nestloop TO off;
The query is quite complex, with aggregate functions, and joins on subqueries, so I gave up on trying to optimize it. Turning off the nestloop solves all my performance issues, and I am fine with that, as long as I turn it on back after the query. Here is an explanation of the problem and the solution. (What are the pitfalls of setting enable_nestloop to OFF)
At the moment, what I do, is wrap the Report query in a database trasaction, and set the enable_nestloop only within that transaction, with SET LOCAL.
with transaction.atomic(), connection.cursor() as cursor:
cursor.execute("SET LOCAL enable_nestloop = off;")
queryset = self.__build_queryset(session, request.query_params)
serializer = MySerializer(queryset, many=True)
response_data = serializer.data
return Response(response_data)
This works good, but I need to remember to do this logic everytime before I execute a SELECT statement on this specific model, otherwise it is painfully slow.
I am looking for a method that will allow me to execute the SET parameter logic before every SELECT query on this model, and afterwards SET the parameter back to the original value. Can I do this on the Model or Manager level?