Si il est intéressant d'utiliser un ORM pour manipuler des objets dans une base de données relationnelle il présente également inconvénient de cacher les requêtes réellement exécutées sur la base de données. Tous les frameworks de développement n'intègre pas forcément de moyen simple d'avoir accés aux requêtes, Django permet de faire cela à partir d'extension comme django-devserver (1[https://github.com/dcramer/django...) ou d'autres ; extensions qui sont utilisables en développement ou sur des machines de pre-prod, mais malheureusement pas en production. Disons que l'on ne s'intéressera pas ici aux sites qui utilisent runserver sur leur serveur de prod, humm.

Résumons le contexte on a une application Django en production et on a besoin de récupérer l'intégralité des commandes SQL passées lors d'une opération de bench.

On va pouvoir faire cela simplement car Django intégre de base un (logger) nommé django.db qui va nous permettre de le faire. On va logger toutes les requêtes directement dans un fichier en configurant dans les settings un handler sur un fichier et en utilisant le logger djangodb.

En pratique on ajoute une entrée file dans la section handlers

    'handlers': {
        'mail_admins': {
            'level': 'ERROR',
            'filters': ['require_debug_false'],
            'class': 'django.utils.log.AdminEmailHandler'
        },
        'file': {
            'level': 'DEBUG',
            'class': 'logging.FileHandler',
            'filename': '/tmp/django-sql.log',
        },
    },

et une entrée django.db dans la section loggers qui utilise l'entrée file

    'loggers': {
        'django.request': {
            'handlers': ['mail_admins'],
            'level': 'ERROR',
            'propagate': True,
        },
        'django.db': {
            'handlers': ['file'],
            'level': 'DEBUG',
            'propagate': True,
            }
    }

On aura toutes nos requêtes sql dans le fichier /tmp/django-sql.log sous la forme

(0.000) SELECT "graph_dashitem"."id", "graph_dashitem"."dash_id", "graph_dashitem"."graph_id", "graph_dashitem"."order" FROM "graph_dashitem" WHERE "graph_dashitem"."dash_id" = 2 ORDER BY "graph_dashitem"."order" ASC; args=(2,)

Le premier champs contient le temps d'exécution et le dernier la liste d'arguments, on obtient un fichier facilement parsable dans lequel on pourra rechercher les requêtes gourmandes en temps par exemple. La prochaine étape sera de passer les requêtes dans EXPLAIN pour les analyser.

Avertissement si votre site a un fort traffic le log de toutes les requêtes va générer beaucoup de consommation d'IO, et d'espace disque, pensez à désactiver les logs quand vous avez finit votre bench.