Search code examples
djangoperformancepostgresqladminpaginator

How to speed up Django's admin pages with PostgreSQL count estimates?


It's quite known that Django's admin list views are getting rather slow when the database tables have lots of rows. That's because the Django paginator uses by default a (slow) PostgreSQL COUNT query.

As estimate would be fine for us and it's much faster, e.g.: SELECT reltuples FROM pg_class WHERE relname = "my_table_name"

There is snippet available to fix this issue, but it's unclear to me how to actually use it: https://djangosnippets.org/snippets/2593/

Also, the snippet is not supposed to work on filtered results. That's because the estimate count as shown above doesn't work here. Is there another way to speed up filtered list views in Django admin pages?


Solution

  • You use it by overriding the ModelAdmin.paginator

    The paginator class to be used for pagination. By default, django.core.paginator.Paginator is used. If the custom paginator class doesn’t have the same constructor interface as django.core.paginator.Paginator, you will also need to provide an implementation for ModelAdmin.get_paginator().

    class MyModelAdmin(admin.ModelAdmin):
        paginator = CachingPaginator
    

    Bonus feature: I have improved on that snippet to create one that works with and without filters: https://gist.github.com/e4c5/6852723 it gets the count from rel_tuples when possible but when a filter is used the count is saved to the cache.

    Update 1:
    The problem with the original snippet reffered to in your answer is due to this change announced in the 1.6 release notes: https://docs.djangoproject.com/en/1.10/releases/1.6/#get-query-set-and-similar-methods-renamed-to-get-queryset

    It's a trivial fix.

    update 2
    My improvement to the original snippet has been made some what obsolete by the _count propert being renamed to count and also it being decorated as a cached_property