I had this problem, except with MySQL. There was an admin page that was taking a very long time to load (15 seconds), but the slowest query was only a few seconds long. Hours of debugging later, I found out what it was.
The mysql database server was indeed returning the results of the query within just a few seconds, but the query hadn't completely finished being processed (through end-of-life, including cleanup) until after the results had returned. Here is a step-by-step explanation of what was going on:
- The expensive query hits the db
- MySQL server returns the query results after a few seconds, but keeps working on clean-up (the query hasn't yet reached end-of-life as far as the mysql server is concerned). The time taken for this query as shown in the django debug toolbar (and django.db.connection.queries) stops timing once results return.
- Django gets back the results and continues to load the page while at the same time, in the background, mysql continues to clean-up the temp table used.
- Django prepares another sql query and sends it to the server.
- MySQL hasn't yet finished cleaning up the temp table, so...
- Django has to sit and wait. Django is using the same mysql db connection as before, and mysql won't let the same connection run another query until the previous one has hit end-of-life, including cleanup.
I figured this out by running "show full processlist;" in a mysql command prompt. For all outstanding queries, it shows the time spent on the query (so far), the status, and the actual query text. Three or 4 seconds after starting the expensive query, it would begin to show "removing tmp table" as the status. It would show this for as long as 7 seconds after the query had already returned results to Django. So apparently MySQL was taking much longer to clean up the query than it was to actually return results. This is exactly what the problem was, in my case.
Interestingly, the "clean up" time didn't show up in the query times of either the offending query nor the follow-up query whose starting was actually delayed.
Not sure if this is your problem, but I suppose it's worth looking into.