{"title":"Optimisation de l’accès à la base de données","version":"6.1","locale":"fr","docname":"topics/db/optimization","url":"/fr/6.1/topics/db/optimization/","canonical":"https://djangodocs.dev/fr/6.1/topics/db/optimization/","summary":"La couche de base de données de Django fournit plusieurs manières d’aider les développeurs à tirer le meilleur de leurs bases de données. Ce document rassemble des…","html":"<h1>Optimisation de l’accès à la base de données<a class=\"heading-anchor\" href=\"#database-access-optimization\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h1>\n<p>La couche de base de données de Django fournit plusieurs manières d’aider les développeurs à tirer le meilleur de leurs bases de données. Ce document rassemble des liens vers la documentation adéquate et ajoute quelques astuces, réparties dans plusieurs chapitres respectant la chronologie des étapes à suivre lorsqu’on souhaite optimiser l’utilisation de la base de données.</p>\n<section id=\"profile-first\">\n<h2>Priorité au profilage<a class=\"heading-anchor\" href=\"#profile-first\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>Comme principe de programmation générale, cela va sans dire. Recherchez <a class=\"reference internal\" href=\"/fr/6.1/faq/models/#faq-see-raw-sql-queries\"><span class=\"std std-ref\">quelles sont les requêtes effectuées et ce qu’elles coûtent</span></a>. Utilisez <a class=\"reference internal\" href=\"/fr/6.1/ref/models/querysets/#django.db.models.query.QuerySet.explain\" title=\"django.db.models.query.QuerySet.explain\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">QuerySet.explain()</span></code></a> pour comprendre comment les requêtes <code class=\"docutils literal notranslate\"><span class=\"pre\">QuerySet</span></code> sont exécutées par la base de données. Il est aussi possible d’utiliser un projet externe comme <a class=\"extlink-pypi reference external\" href=\"https://pypi.org/project/django-debug-toolbar/\">django-debug-toolbar</a> ou un outil qui surveille directement la base de données.</p>\n<p>Rappelez-vous que l’on peut optimiser pour la rapidité, pour la mémoire ou pour les deux, en fonction des besoins. Parfois, l’optimisation d’un côté va péjorer la situation de l’autre, mais dans d’autres cas, les deux vont en profiter ensemble. De plus, le travail effectué par le processus de la base de données n’a pas toujours le même coût (pour vous) que le même travail effectué dans le processus Python. C’est à vous de décider des priorités, de pondérer avantages et inconvénients et de profiler tout cela selon les besoins car tout dépend de votre application et du serveur.</p>\n<p>Avec tout ce qui suit, n’oubliez pas de profiler après chaque modification pour vous assurer que celle-ci est bénéfique et que le bénéfice est suffisant pour compenser la perte de lisibilité du code. Pour <strong>toutes</strong> les suggestions ci-dessous, il faut tenir compte du risque que le principe général ne s’applique pas dans votre cas de figure, ou que l’effet soit même inversé.</p>\n</section>\n<section id=\"use-standard-db-optimization-techniques\">\n<h2>Techniques standards d’optimisation de base de données<a class=\"heading-anchor\" href=\"#use-standard-db-optimization-techniques\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>Ceci comprend :</p>\n<ul class=\"simple\">\n<li><p>Des <a class=\"reference external\" href=\"https://en.wikipedia.org/wiki/Database_index\">index</a>. C’est la priorité n°1, <em>après</em> avoir déterminé par analyse de performance quels sont les index nécessaires. Utilisez <a class=\"reference internal\" href=\"/fr/6.1/ref/models/options/#django.db.models.Options.indexes\" title=\"django.db.models.Options.indexes\"><code class=\"xref py py-attr docutils literal notranslate\"><span class=\"pre\">Meta.indexes</span></code></a> ou <a class=\"reference internal\" href=\"/fr/6.1/ref/models/fields/#django.db.models.Field.db_index\" title=\"django.db.models.Field.db_index\"><code class=\"xref py py-attr docutils literal notranslate\"><span class=\"pre\">Field.db_index</span></code></a> pour en ajouter à partir de Django. Envisagez l’utilisation d’index aux champs que vous interrogez fréquemment avec <a class=\"reference internal\" href=\"/fr/6.1/ref/models/querysets/#django.db.models.query.QuerySet.filter\" title=\"django.db.models.query.QuerySet.filter\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">filter()</span></code></a>, <a class=\"reference internal\" href=\"/fr/6.1/ref/models/querysets/#django.db.models.query.QuerySet.exclude\" title=\"django.db.models.query.QuerySet.exclude\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">exclude()</span></code></a>, <a class=\"reference internal\" href=\"/fr/6.1/ref/models/querysets/#django.db.models.query.QuerySet.order_by\" title=\"django.db.models.query.QuerySet.order_by\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">order_by()</span></code></a>, etc. car les index peuvent aider à accélérer les requêtes. Notez que la recherche des meilleurs index est un thème complexe et dépendant du moteur de base de données, également dépendant de l’application à construire. La charge induite par la maintenance d’un index peut anéantir les gains en terme de vitesse de requête.</p></li>\n</ul>\n<ul class=\"simple\">\n<li><p>Utilisation appropriée des types de champs.</p></li>\n</ul>\n<p>Nous supposerons que vous avez effectué les opérations mentionnées ci-dessus. La suite de ce document se concentre sur la façon d’utiliser Django de telle manière à ne pas effectuer de travail inutile. Ce document n’aborde cependant pas d’autres techniques d’optimisation qui s’appliquent à des opérations lourdes, comme la <a class=\"reference internal\" href=\"/fr/6.1/topics/cache/\"><span class=\"doc\">mise en cache à portée générale</span></a>.</p>\n</section>\n<section id=\"understand-querysets\">\n<h2>Compréhension des objets <code class=\"docutils literal notranslate\"><span class=\"pre\">QuerySet</span></code><a class=\"heading-anchor\" href=\"#understand-querysets\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>La compréhension des <a class=\"reference internal\" href=\"/fr/6.1/ref/models/querysets/\"><span class=\"doc\">QuerySet</span></a> est capitale pour obtenir de bonnes performances avec du code simple. En particulier :</p>\n<section id=\"understand-queryset-evaluation\">\n<h3>Compréhension de l’évaluation du <code class=\"docutils literal notranslate\"><span class=\"pre\">QuerySet</span></code><a class=\"heading-anchor\" href=\"#understand-queryset-evaluation\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Pour éviter des problèmes de performance, il est important de comprendre :</p>\n<ul class=\"simple\">\n<li><p>que les <a class=\"reference internal\" href=\"/fr/6.1/topics/db/queries/#querysets-are-lazy\"><span class=\"std std-ref\">QuerySet sont différés</span></a>.</p></li>\n<li><p>quand <a class=\"reference internal\" href=\"/fr/6.1/ref/models/querysets/#when-querysets-are-evaluated\"><span class=\"std std-ref\">ils sont évalués</span></a>.</p></li>\n<li><p>comment <a class=\"reference internal\" href=\"/fr/6.1/topics/db/queries/#caching-and-querysets\"><span class=\"std std-ref\">les données sont conservée en mémoire</span></a>.</p></li>\n</ul>\n</section>\n<section id=\"understand-cached-attributes\">\n<h3>Compréhension des attributs mis en cache<a class=\"heading-anchor\" href=\"#understand-cached-attributes\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Tout comme la mise en cache d’un <code class=\"docutils literal notranslate\"><span class=\"pre\">QuerySet</span></code> global, il y a mise en cache du résultat des attributs dans les objets de l’ORM. En général, les attributs qui ne sont pas exécutables seront mis en cache. Par exemple, à partir des <a class=\"reference internal\" href=\"/fr/6.1/topics/db/queries/#queryset-model-example\"><span class=\"std std-ref\">modèles d’exemple du blog</span></a>:</p>\n<div class=\"code-block\" data-language=\"pycon\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Python console</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Python console code\"><code><span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">entry</span> <span class=\"o\">=</span> <span class=\"n\">Entry</span><span class=\"o\">.</span><span class=\"n\">objects</span><span class=\"o\">.</span><span class=\"n\">get</span><span class=\"p\">(</span><span class=\"nb\">id</span><span class=\"o\">=</span><span class=\"mi\">1</span><span class=\"p\">)</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">entry</span><span class=\"o\">.</span><span class=\"n\">blog</span>  <span class=\"c1\"># Blog object is retrieved at this point</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">entry</span><span class=\"o\">.</span><span class=\"n\">blog</span>  <span class=\"c1\"># cached version, no DB access</span>\n</code></pre></div>\n<p>Mais généralement, les attributs exécutables provoquent des accès à la base de données à chaque appel :</p>\n<div class=\"code-block\" data-language=\"pycon\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Python console</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Python console code\"><code><span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">entry</span> <span class=\"o\">=</span> <span class=\"n\">Entry</span><span class=\"o\">.</span><span class=\"n\">objects</span><span class=\"o\">.</span><span class=\"n\">get</span><span class=\"p\">(</span><span class=\"nb\">id</span><span class=\"o\">=</span><span class=\"mi\">1</span><span class=\"p\">)</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">entry</span><span class=\"o\">.</span><span class=\"n\">authors</span><span class=\"o\">.</span><span class=\"n\">all</span><span class=\"p\">()</span>  <span class=\"c1\"># query performed</span>\n<span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">entry</span><span class=\"o\">.</span><span class=\"n\">authors</span><span class=\"o\">.</span><span class=\"n\">all</span><span class=\"p\">()</span>  <span class=\"c1\"># query performed again</span>\n</code></pre></div>\n<p>Soyez prudent dans la lecture du code des gabarits, le système des gabarits ne permet pas d’utiliser des parenthèses, mais les objets exécutables sont appelés automatiquement, masquant la distinction ci-dessus.</p>\n<p>Soyez prudent avec vos propres propriétés personnalisées, il vous revient d’implémenter leur mise en cache au besoin, par exemple en utilisant le décorateur <a class=\"reference internal\" href=\"/fr/6.1/ref/utils/#django.utils.functional.cached_property\" title=\"django.utils.functional.cached_property\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">cached_property</span></code></a>.</p>\n</section>\n<section id=\"use-the-with-template-tag\">\n<h3>Utilisation de la balise de gabarit <code class=\"docutils literal notranslate\"><span class=\"pre\">with</span></code><a class=\"heading-anchor\" href=\"#use-the-with-template-tag\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Pour faire usage du comportement de cache de <code class=\"docutils literal notranslate\"><span class=\"pre\">QuerySet</span></code>, il peut être nécessaire d’utiliser la balise de gabarit <a class=\"reference internal\" href=\"/fr/6.1/ref/templates/builtins/#std-templatetag-with\"><code class=\"xref std std-ttag docutils literal notranslate\"><span class=\"pre\">with</span></code></a>.</p>\n</section>\n<section id=\"use-iterator\">\n<h3>Utilisation de <code class=\"docutils literal notranslate\"><span class=\"pre\">iterator()</span></code><a class=\"heading-anchor\" href=\"#use-iterator\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Lorsque vous manipulez un grand nombre d’objets, le comportement de cache de <code class=\"docutils literal notranslate\"><span class=\"pre\">QuerySet</span></code> peut provoquer une grosse utilisation de la mémoire. Dans ce cas, <a class=\"reference internal\" href=\"/fr/6.1/ref/models/querysets/#django.db.models.query.QuerySet.iterator\" title=\"django.db.models.query.QuerySet.iterator\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">iterator()</span></code></a> peut aider.</p>\n</section>\n<section id=\"use-explain\">\n<h3>Utilisation de <code class=\"docutils literal notranslate\"><span class=\"pre\">explain()</span></code><a class=\"heading-anchor\" href=\"#use-explain\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h3>\n<p><a class=\"reference internal\" href=\"/fr/6.1/ref/models/querysets/#django.db.models.query.QuerySet.explain\" title=\"django.db.models.query.QuerySet.explain\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">QuerySet.explain()</span></code></a> apporte des informations détaillées sur la façon dont la base de données exécute les requêtes, y compris les index et jointures utilisées. Ces détails peuvent aider à trouver les requêtes qui pourraient être réécrites plus efficacement ou à identifier des index qui pourraient être ajoutés pour améliorer les performances.</p>\n</section>\n</section>\n<section id=\"do-database-work-in-the-database-rather-than-in-python\">\n<h2>Travail de base de données en base de données plutôt qu’en Python<a class=\"heading-anchor\" href=\"#do-database-work-in-the-database-rather-than-in-python\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>Par exemple :</p>\n<ul class=\"simple\">\n<li><p>Au niveau le plus élémentaire, utilisez <a class=\"reference internal\" href=\"/fr/6.1/ref/models/querysets/#queryset-api\"><span class=\"std std-ref\">filter et exclude</span></a> pour filtrer au niveau de la base de données.</p></li>\n<li><p>Use <a class=\"reference internal\" href=\"/fr/6.1/ref/models/expressions/#f-expressions\"><span class=\"std std-ref\">Expressions F()</span></a> to filter based on other fields within the same\nmodel.</p></li>\n<li><p>Utilisez les <a class=\"reference internal\" href=\"/fr/6.1/topics/db/aggregation/\"><span class=\"doc\">annotations pour effectuer le travail d’agrégation dans la base de données</span></a>.</p></li>\n</ul>\n<p>Si ces outils ne suffisent pas à générer le code SQL nécessaire :</p>\n<section id=\"use-rawsql\">\n<h3>Utilisation de <code class=\"docutils literal notranslate\"><span class=\"pre\">RawSQL</span></code><a class=\"heading-anchor\" href=\"#use-rawsql\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Une méthode moins portable mais plus puissante est d’utiliser l’expression <a class=\"reference internal\" href=\"/fr/6.1/ref/models/expressions/#django.db.models.expressions.RawSQL\" title=\"django.db.models.expressions.RawSQL\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">RawSQL</span></code></a> qui permet d’ajouter explicitement du code SQL dans une requête. Si cela ne suffit toujours pas :</p>\n</section>\n<section id=\"use-raw-sql\">\n<h3>Utilisation de SQL brut<a class=\"heading-anchor\" href=\"#use-raw-sql\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Écrivez votre <a class=\"reference internal\" href=\"/fr/6.1/topics/db/sql/\"><span class=\"doc\">propre code SQL pour sélectionner des données ou remplir les modèles</span></a>. Utilisez <code class=\"docutils literal notranslate\"><span class=\"pre\">django.db.connection.queries</span></code> pour examiner ce que Django écrit pour vous et considérez cela comme un point de départ.</p>\n</section>\n</section>\n<section id=\"retrieve-individual-objects-using-a-unique-indexed-column\">\n<h2>Sélection d’objets individuels en utilisant une colonne unique et indexée<a class=\"heading-anchor\" href=\"#retrieve-individual-objects-using-a-unique-indexed-column\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>Il y a deux raisons d’utiliser une colonne avec <a class=\"reference internal\" href=\"/fr/6.1/ref/models/fields/#django.db.models.Field.unique\" title=\"django.db.models.Field.unique\"><code class=\"xref py py-attr docutils literal notranslate\"><span class=\"pre\">unique</span></code></a> ou <a class=\"reference internal\" href=\"/fr/6.1/ref/models/fields/#django.db.models.Field.db_index\" title=\"django.db.models.Field.db_index\"><code class=\"xref py py-attr docutils literal notranslate\"><span class=\"pre\">db_index</span></code></a> lorsqu’on utilise <a class=\"reference internal\" href=\"/fr/6.1/ref/models/querysets/#django.db.models.query.QuerySet.get\" title=\"django.db.models.query.QuerySet.get\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">get()</span></code></a> pour récupérer des objets individuels. Premièrement, la requête sera plus rapide en raison de l’index de base de données. De plus, la requête pourrait s’effectuer beaucoup plus lentement si plusieurs objets correspondent à la recherche ; avec une contrainte d’unicité sur la colonne, vous avez la garantie que cela ne se produira jamais.</p>\n<p>Ainsi, en se basant sur les <a class=\"reference internal\" href=\"/fr/6.1/topics/db/queries/#queryset-model-example\"><span class=\"std std-ref\">modèles d’exemple du blog</span></a>:</p>\n<div class=\"code-block\" data-language=\"pycon\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Python console</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Python console code\"><code><span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">entry</span> <span class=\"o\">=</span> <span class=\"n\">Entry</span><span class=\"o\">.</span><span class=\"n\">objects</span><span class=\"o\">.</span><span class=\"n\">get</span><span class=\"p\">(</span><span class=\"nb\">id</span><span class=\"o\">=</span><span class=\"mi\">10</span><span class=\"p\">)</span>\n</code></pre></div>\n<p>sera plus rapide que :</p>\n<div class=\"code-block\" data-language=\"pycon\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Python console</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Python console code\"><code><span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">entry</span> <span class=\"o\">=</span> <span class=\"n\">Entry</span><span class=\"o\">.</span><span class=\"n\">objects</span><span class=\"o\">.</span><span class=\"n\">get</span><span class=\"p\">(</span><span class=\"n\">headline</span><span class=\"o\">=</span><span class=\"s2\">&quot;News Item Title&quot;</span><span class=\"p\">)</span>\n</code></pre></div>\n<p>parce qu”<code class=\"docutils literal notranslate\"><span class=\"pre\">id</span></code> est indexé dans la base de données et que son unicité est garantie.</p>\n<p>La ligne suivante est potentiellement très lente :</p>\n<div class=\"code-block\" data-language=\"pycon\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Python console</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Python console code\"><code><span class=\"gp\">&gt;&gt;&gt; </span><span class=\"n\">entry</span> <span class=\"o\">=</span> <span class=\"n\">Entry</span><span class=\"o\">.</span><span class=\"n\">objects</span><span class=\"o\">.</span><span class=\"n\">get</span><span class=\"p\">(</span><span class=\"n\">headline__startswith</span><span class=\"o\">=</span><span class=\"s2\">&quot;News&quot;</span><span class=\"p\">)</span>\n</code></pre></div>\n<p>Tout d’abord, <code class=\"docutils literal notranslate\"><span class=\"pre\">headline</span></code> n’est pas indexé, ce qui fait que la base de données sous-jacente prendra plus de temps pour trouver la ligne.</p>\n<p>Second, the lookup may return multiple results. Even though Django applies a\nlimit of 21 objects when using <a class=\"reference internal\" href=\"/fr/6.1/ref/models/querysets/#django.db.models.query.QuerySet.get\" title=\"django.db.models.query.QuerySet.get\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">get()</span></code></a>,\nthe database may still need to scan everything to evaluate a non-unique\ncondition. Narrowing your query up-front is more efficient.</p>\n</section>\n<section id=\"retrieve-related-objects-efficiently\">\n<h2>Retrieve related objects efficiently<a class=\"heading-anchor\" href=\"#retrieve-related-objects-efficiently\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>Generally, accessing the database multiple times to retrieve different parts\nof a single « set » of data is less efficient than retrieving it all in one\nquery. This is particularly important if you have a query that is executed in a\nloop, and could therefore end up doing many database queries, when only one\nis needed. Below are some techniques to combine queries for efficiency.</p>\n<section id=\"use-the-fetch-peers-fetch-mode\">\n<h3>Use the <code class=\"docutils literal notranslate\"><span class=\"pre\">FETCH_PEERS</span></code> fetch mode<a class=\"heading-anchor\" href=\"#use-the-fetch-peers-fetch-mode\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Use the <a class=\"reference internal\" href=\"/fr/6.1/topics/db/fetch-modes/#django.db.models.FETCH_PEERS\" title=\"django.db.models.FETCH_PEERS\"><code class=\"xref py py-attr docutils literal notranslate\"><span class=\"pre\">FETCH_PEERS</span></code></a> fetch mode to make on-demand\nfield access more efficient with bulk-fetching. Enable it for all usage of\nyour models <a class=\"reference internal\" href=\"/fr/6.1/topics/db/fetch-modes/#fetch-modes-custom-manager\"><span class=\"std std-ref\">with a custom manager</span></a>.</p>\n<p>Using this fetch mode is easier than declaring fields to fetch with\n<a class=\"reference internal\" href=\"/fr/6.1/ref/models/querysets/#django.db.models.query.QuerySet.select_related\" title=\"django.db.models.query.QuerySet.select_related\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">select_related()</span></code></a> or\n<a class=\"reference internal\" href=\"/fr/6.1/ref/models/querysets/#django.db.models.query.QuerySet.prefetch_related\" title=\"django.db.models.query.QuerySet.prefetch_related\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">prefetch_related()</span></code></a>, especially when it’s\nhard to predict which fields will be accessed.</p>\n</section>\n<section id=\"use-queryset-select-related-and-prefetch-related\">\n<h3>Utilisation de <code class=\"docutils literal notranslate\"><span class=\"pre\">QuerySet.select_related()</span></code> et <code class=\"docutils literal notranslate\"><span class=\"pre\">prefetch_related()</span></code><a class=\"heading-anchor\" href=\"#use-queryset-select-related-and-prefetch-related\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>When the <a class=\"reference internal\" href=\"/fr/6.1/topics/db/fetch-modes/#django.db.models.FETCH_PEERS\" title=\"django.db.models.FETCH_PEERS\"><code class=\"xref py py-attr docutils literal notranslate\"><span class=\"pre\">FETCH_PEERS</span></code></a> fetch mode is not appropriate or\nefficient enough, use <a class=\"reference internal\" href=\"/fr/6.1/ref/models/querysets/#django.db.models.query.QuerySet.select_related\" title=\"django.db.models.query.QuerySet.select_related\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">select_related()</span></code></a>\nand <a class=\"reference internal\" href=\"/fr/6.1/ref/models/querysets/#django.db.models.query.QuerySet.prefetch_related\" title=\"django.db.models.query.QuerySet.prefetch_related\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">prefetch_related()</span></code></a>. Understand their\ndocumentation thoroughly and apply them where needed.</p>\n<p>It may be useful to apply these methods in <a class=\"reference internal\" href=\"/fr/6.1/topics/db/managers/\"><span class=\"doc\">managers and default managers</span></a>. Be aware when your manager is and is not used; for\nexample, related object access <a class=\"reference internal\" href=\"/fr/6.1/topics/db/managers/#managers-for-related-objects\"><span class=\"std std-ref\">uses the base manager</span></a> rather than the default manager.</p>\n</section>\n<section id=\"use-prefetch-related-objects\">\n<h3>Use <code class=\"docutils literal notranslate\"><span class=\"pre\">prefetch_related_objects()</span></code><a class=\"heading-anchor\" href=\"#use-prefetch-related-objects\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Where <a class=\"reference internal\" href=\"/fr/6.1/ref/models/querysets/#django.db.models.query.QuerySet.prefetch_related\" title=\"django.db.models.query.QuerySet.prefetch_related\"><code class=\"xref py py-attr docutils literal notranslate\"><span class=\"pre\">prefetch_related</span></code></a> would be useful\nafter the queryset has been evaluated, use\n<a class=\"reference internal\" href=\"/fr/6.1/ref/models/querysets/#django.db.models.prefetch_related_objects\" title=\"django.db.models.prefetch_related_objects\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">prefetch_related_objects()</span></code></a> to execute an extra\nprefetch.</p>\n</section>\n</section>\n<section id=\"don-t-retrieve-things-you-don-t-need\">\n<h2>Ne pas récupérer des éléments inutilement<a class=\"heading-anchor\" href=\"#don-t-retrieve-things-you-don-t-need\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h2>\n<section id=\"use-queryset-values-and-values-list\">\n<h3>Utilisation de <code class=\"docutils literal notranslate\"><span class=\"pre\">QuerySet.values()</span></code> et <code class=\"docutils literal notranslate\"><span class=\"pre\">values_list()</span></code><a class=\"heading-anchor\" href=\"#use-queryset-values-and-values-list\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Lorsque vous ne voulez qu’obtenir un dictionnaire ou une liste de valeurs sans avoir besoin d’objets modèles de l’ORM, faites bon usage de <a class=\"reference internal\" href=\"/fr/6.1/ref/models/querysets/#django.db.models.query.QuerySet.values\" title=\"django.db.models.query.QuerySet.values\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">values()</span></code></a>. Cette méthode peut être utile pour remplacer des objets modèles dans le code des gabarits ; tant que les dictionnaires résultants possèdent les mêmes attributs que ceux qui sont utilisés dans le gabarit, tout va bien.</p>\n</section>\n<section id=\"use-queryset-defer-and-only\">\n<h3>Utilisation de <code class=\"docutils literal notranslate\"><span class=\"pre\">QuerySet.defer()</span></code> et <code class=\"docutils literal notranslate\"><span class=\"pre\">only()</span></code><a class=\"heading-anchor\" href=\"#use-queryset-defer-and-only\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Utilisez <a class=\"reference internal\" href=\"/fr/6.1/ref/models/querysets/#django.db.models.query.QuerySet.defer\" title=\"django.db.models.query.QuerySet.defer\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">defer()</span></code></a> et <a class=\"reference internal\" href=\"/fr/6.1/ref/models/querysets/#django.db.models.query.QuerySet.only\" title=\"django.db.models.query.QuerySet.only\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">only()</span></code></a> quand vous savez à l’avance que vous n’aurez pas besoin de certaines colonnes de base de données (ou non utiles dans la plupart des cas) afin d’éviter de les charger. Notez que si vous les utilisez quand même, l’ORM devra les charger à l’aide d’une nouvelle requête, ce qui peut potentiellement aggraver la situation quand cette technique n’est pas utilisée à bon escient.</p>\n<p>N’utilisez pas trop agressivement les champs différés sans profilage car la base de données doit lire sur le disque la plupart des données non textuelles et non <code class=\"docutils literal notranslate\"><span class=\"pre\">VARCHAR</span></code> d’un enregistrement des résultats, même lorsqu’elle finit par n’exploiter que quelques colonnes. Les méthodes <code class=\"docutils literal notranslate\"><span class=\"pre\">defer()</span></code> et <code class=\"docutils literal notranslate\"><span class=\"pre\">only()</span></code> sont particulièrement adéquates lorsqu’on peut éviter de charger de grandes quantités de données textuelles ou quand la valeur de certains champs est coûteuse en terme de conversion en Python. Comme toujours, profilez d’abord, optimisez ensuite.</p>\n</section>\n<section id=\"use-queryset-contains-obj\">\n<h3>Utilisation de <code class=\"docutils literal notranslate\"><span class=\"pre\">QuerySet.contains(obj)</span></code><a class=\"heading-anchor\" href=\"#use-queryset-contains-obj\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>…si vous voulez uniquement savoir si <code class=\"docutils literal notranslate\"><span class=\"pre\">obj</span></code> est présent dans le résultat de requête, au lieu de <code class=\"docutils literal notranslate\"><span class=\"pre\">if</span> <span class=\"pre\">obj</span> <span class=\"pre\">in</span> <span class=\"pre\">queryset</span></code>.</p>\n</section>\n<section id=\"use-queryset-count\">\n<h3>Utilisation de <code class=\"docutils literal notranslate\"><span class=\"pre\">QuerySet.count()</span></code><a class=\"heading-anchor\" href=\"#use-queryset-count\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>…si vous n’avez besoin que du nombre de lignes, et évitez <code class=\"docutils literal notranslate\"><span class=\"pre\">len(queryset)</span></code>.</p>\n</section>\n<section id=\"use-queryset-exists\">\n<h3>Utilisation de <code class=\"docutils literal notranslate\"><span class=\"pre\">QuerySet.exists()</span></code><a class=\"heading-anchor\" href=\"#use-queryset-exists\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>…si vous voulez uniquement savoir qu’il y a au moins un résultat, et évitez <code class=\"docutils literal notranslate\"><span class=\"pre\">if</span> <span class=\"pre\">queryset</span></code>.</p>\n<p>Mais :</p>\n</section>\n<section id=\"don-t-overuse-contains-count-and-exists\">\n<span id=\"overuse-of-count-and-exists\"></span><h3>Ne pas abuser de <code class=\"docutils literal notranslate\"><span class=\"pre\">contains()</span></code>, <code class=\"docutils literal notranslate\"><span class=\"pre\">count()</span></code> et <code class=\"docutils literal notranslate\"><span class=\"pre\">exists()</span></code><a class=\"heading-anchor\" href=\"#don-t-overuse-contains-count-and-exists\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Si vous allez avoir besoin de données réelles du <code class=\"docutils literal notranslate\"><span class=\"pre\">QuerySet</span></code>, évaluez-le immédiatement.</p>\n<p>Par exemple, si on dispose d’un modèle <code class=\"docutils literal notranslate\"><span class=\"pre\">Group</span></code> ayant une relation plusieurs-à-plusieurs vers <code class=\"docutils literal notranslate\"><span class=\"pre\">User</span></code>, le code suivant est optimal :</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"n\">members</span> <span class=\"o\">=</span> <span class=\"n\">group</span><span class=\"o\">.</span><span class=\"n\">members</span><span class=\"o\">.</span><span class=\"n\">all</span><span class=\"p\">()</span>\n\n<span class=\"k\">if</span> <span class=\"n\">display_group_members</span><span class=\"p\">:</span>\n    <span class=\"k\">if</span> <span class=\"n\">members</span><span class=\"p\">:</span>\n        <span class=\"k\">if</span> <span class=\"n\">current_user</span> <span class=\"ow\">in</span> <span class=\"n\">members</span><span class=\"p\">:</span>\n            <span class=\"nb\">print</span><span class=\"p\">(</span><span class=\"s2\">&quot;You and&quot;</span><span class=\"p\">,</span> <span class=\"nb\">len</span><span class=\"p\">(</span><span class=\"n\">members</span><span class=\"p\">)</span> <span class=\"o\">-</span> <span class=\"mi\">1</span><span class=\"p\">,</span> <span class=\"s2\">&quot;other users are members of this group.&quot;</span><span class=\"p\">)</span>\n        <span class=\"k\">else</span><span class=\"p\">:</span>\n            <span class=\"nb\">print</span><span class=\"p\">(</span><span class=\"s2\">&quot;There are&quot;</span><span class=\"p\">,</span> <span class=\"nb\">len</span><span class=\"p\">(</span><span class=\"n\">members</span><span class=\"p\">),</span> <span class=\"s2\">&quot;members in this group.&quot;</span><span class=\"p\">)</span>\n\n        <span class=\"k\">for</span> <span class=\"n\">member</span> <span class=\"ow\">in</span> <span class=\"n\">members</span><span class=\"p\">:</span>\n            <span class=\"nb\">print</span><span class=\"p\">(</span><span class=\"n\">member</span><span class=\"o\">.</span><span class=\"n\">username</span><span class=\"p\">)</span>\n    <span class=\"k\">else</span><span class=\"p\">:</span>\n        <span class=\"nb\">print</span><span class=\"p\">(</span><span class=\"s2\">&quot;There are no members in this group.&quot;</span><span class=\"p\">)</span>\n</code></pre></div>\n<p>Il est optimal car :</p>\n<ol class=\"arabic simple\">\n<li><p>Comme les objets QuerySet sont différés, aucune requête de base de données n’est exécutée si <code class=\"docutils literal notranslate\"><span class=\"pre\">display_group_members</span></code> vaut <code class=\"docutils literal notranslate\"><span class=\"pre\">False</span></code>.</p></li>\n<li><p>Le stockage de <code class=\"docutils literal notranslate\"><span class=\"pre\">group.members.all()</span></code> dans la variable <code class=\"docutils literal notranslate\"><span class=\"pre\">members</span></code> permet de réutiliser son résultat mis en cache.</p></li>\n<li><p>La ligne <code class=\"docutils literal notranslate\"><span class=\"pre\">if</span> <span class=\"pre\">members:</span></code> provoque l’appel à <code class=\"docutils literal notranslate\"><span class=\"pre\">QuerySet.__bool__()</span></code>, ce qui provoque aussi l’exécution de la requête <code class=\"docutils literal notranslate\"><span class=\"pre\">group.members.all()</span></code> dans la base de données. S’il n’y a pas de résultats, elle renvoie <code class=\"docutils literal notranslate\"><span class=\"pre\">False</span></code>, sinon <code class=\"docutils literal notranslate\"><span class=\"pre\">True</span></code>.</p></li>\n<li><p>La ligne <code class=\"docutils literal notranslate\"><span class=\"pre\">if</span> <span class=\"pre\">current_user</span> <span class=\"pre\">in</span> <span class=\"pre\">members:</span></code> vérifie si l’utilisateur est dans le cache de résultats, donc aucune requête de base de données supplémentaire n’est effectuée.</p></li>\n<li><p>L’emploi de <code class=\"docutils literal notranslate\"><span class=\"pre\">len(members)</span></code> appelle <code class=\"docutils literal notranslate\"><span class=\"pre\">QuerySet.__len__()</span></code>, réutilisant le résultat mis en cache, donc toujours sans requête supplémentaire vers la base de données.</p></li>\n<li><p>La boucle <code class=\"docutils literal notranslate\"><span class=\"pre\">for</span> <span class=\"pre\">member</span></code> utilise les données du cache.</p></li>\n</ol>\n<p>Au total, le code effectue une ou zéro requête de base de données. La seule optimisation explicite effectuée est l’emploi de la variable <code class=\"docutils literal notranslate\"><span class=\"pre\">members</span></code>. Si on avait utilisé <code class=\"docutils literal notranslate\"><span class=\"pre\">QuerySet.exists()</span></code> pour le <code class=\"docutils literal notranslate\"><span class=\"pre\">if</span></code>, <code class=\"docutils literal notranslate\"><span class=\"pre\">QuerySet.contains()</span></code> pour le <code class=\"docutils literal notranslate\"><span class=\"pre\">in</span></code> ou <code class=\"docutils literal notranslate\"><span class=\"pre\">QuerySet.count()</span></code> pour le nombre total, cela aurait généré à chaque fois des requêtes supplémentaires.</p>\n</section>\n<section id=\"use-queryset-update-and-delete\">\n<h3>Utilisation de <code class=\"docutils literal notranslate\"><span class=\"pre\">QuerySet.update()</span></code> et <code class=\"docutils literal notranslate\"><span class=\"pre\">delete()</span></code><a class=\"heading-anchor\" href=\"#use-queryset-update-and-delete\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Plutôt que de récupérer un ensemble d’objets, de définir certaines valeurs et de les enregistrer individuellement, utilisez une instruction SQL UPDATE groupée au moyen de <a class=\"reference internal\" href=\"/fr/6.1/topics/db/queries/#topics-db-queries-update\"><span class=\"std std-ref\">QuerySet.update()</span></a>. De la même façon, effectuez des <a class=\"reference internal\" href=\"/fr/6.1/topics/db/queries/#topics-db-queries-delete\"><span class=\"std std-ref\">suppressions groupées</span></a> chaque fois que c’est possible.</p>\n<p>Notez cependant que des méthodes de mise à jour groupées ne peuvent pas appeler les méthodes <code class=\"docutils literal notranslate\"><span class=\"pre\">save()</span></code> et <code class=\"docutils literal notranslate\"><span class=\"pre\">delete()</span></code> des instances individuelles, ce qui signifie que tout comportement spécialisé que vous auriez ajouté avec ces méthodes ne sera pas exécuté, y compris tout ce qui découle de l’utilisation des <a class=\"reference internal\" href=\"/fr/6.1/ref/signals/\"><span class=\"doc\">signaux</span></a> attachés aux objets de base de données.</p>\n</section>\n<section id=\"use-foreign-key-values-directly\">\n<h3>Utilisation directe de valeurs de clé étrangère<a class=\"heading-anchor\" href=\"#use-foreign-key-values-directly\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Si vous n’avez besoin que de la valeur d’une clé étrangère, utilisez la valeur qui est déjà stockée dans l’objet que vous manipulez, plutôt que de récupérer tout l’objet lié pour simplement disposer de sa clé primaire. Par exemple, faites :</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"n\">entry</span><span class=\"o\">.</span><span class=\"n\">blog_id</span>\n</code></pre></div>\n<p>au lieu de :</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"n\">entry</span><span class=\"o\">.</span><span class=\"n\">blog</span><span class=\"o\">.</span><span class=\"n\">id</span>\n</code></pre></div>\n</section>\n<section id=\"don-t-order-results-if-you-don-t-care\">\n<h3>Ne pas trier les résultats sans raison<a class=\"heading-anchor\" href=\"#don-t-order-results-if-you-don-t-care\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Le tri n’est pas gratuit ; chaque champ de tri est une opération que la base de données doit effectuer. Si un modèle possède un ordre de tri par défaut (<a class=\"reference internal\" href=\"/fr/6.1/ref/models/options/#django.db.models.Options.ordering\" title=\"django.db.models.Options.ordering\"><code class=\"xref py py-attr docutils literal notranslate\"><span class=\"pre\">Meta.ordering</span></code></a>) et que vous n’en avez pas besoin, vous pouvez l’enlever sur un <code class=\"docutils literal notranslate\"><span class=\"pre\">QuerySet</span></code> en appelant <a class=\"reference internal\" href=\"/fr/6.1/ref/models/querysets/#django.db.models.query.QuerySet.order_by\" title=\"django.db.models.query.QuerySet.order_by\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">order_by()</span></code></a> sans paramètre.</p>\n<p>L’ajout d’un index à votre base de données peut aider à améliorer les performances de tri.</p>\n</section>\n</section>\n<section id=\"use-bulk-methods\">\n<h2>Utiliser les méthodes d’opérations groupées<a class=\"heading-anchor\" href=\"#use-bulk-methods\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>Faites usage des méthodes groupées (<code class=\"docutils literal notranslate\"><span class=\"pre\">bulk</span></code>) pour réduire le nombre d’instructions SQL.</p>\n<section id=\"create-in-bulk\">\n<h3>Création groupée<a class=\"heading-anchor\" href=\"#create-in-bulk\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Lors de la création d’objets, utilisez si possible la méthode <a class=\"reference internal\" href=\"/fr/6.1/ref/models/querysets/#django.db.models.query.QuerySet.bulk_create\" title=\"django.db.models.query.QuerySet.bulk_create\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">bulk_create()</span></code></a> pour réduire le nombre de requêtes SQL. Par exemple :</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"n\">Entry</span><span class=\"o\">.</span><span class=\"n\">objects</span><span class=\"o\">.</span><span class=\"n\">bulk_create</span><span class=\"p\">(</span>\n    <span class=\"p\">[</span>\n        <span class=\"n\">Entry</span><span class=\"p\">(</span><span class=\"n\">headline</span><span class=\"o\">=</span><span class=\"s2\">&quot;This is a test&quot;</span><span class=\"p\">),</span>\n        <span class=\"n\">Entry</span><span class=\"p\">(</span><span class=\"n\">headline</span><span class=\"o\">=</span><span class=\"s2\">&quot;This is only a test&quot;</span><span class=\"p\">),</span>\n    <span class=\"p\">]</span>\n<span class=\"p\">)</span>\n</code></pre></div>\n<p>…est préférable à :</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"n\">Entry</span><span class=\"o\">.</span><span class=\"n\">objects</span><span class=\"o\">.</span><span class=\"n\">create</span><span class=\"p\">(</span><span class=\"n\">headline</span><span class=\"o\">=</span><span class=\"s2\">&quot;This is a test&quot;</span><span class=\"p\">)</span>\n<span class=\"n\">Entry</span><span class=\"o\">.</span><span class=\"n\">objects</span><span class=\"o\">.</span><span class=\"n\">create</span><span class=\"p\">(</span><span class=\"n\">headline</span><span class=\"o\">=</span><span class=\"s2\">&quot;This is only a test&quot;</span><span class=\"p\">)</span>\n</code></pre></div>\n<p>Note that <a class=\"reference internal\" href=\"/fr/6.1/ref/models/querysets/#django.db.models.query.QuerySet.bulk_create\" title=\"django.db.models.query.QuerySet.bulk_create\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">bulk_create()</span></code></a> has several\ncaveats, so ensure it’s appropriate for your use case.</p>\n</section>\n<section id=\"update-in-bulk\">\n<h3>Mise à jour groupée<a class=\"heading-anchor\" href=\"#update-in-bulk\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Lors de la mise à jour d’objets, utilisez si possible la méthode <a class=\"reference internal\" href=\"/fr/6.1/ref/models/querysets/#django.db.models.query.QuerySet.bulk_update\" title=\"django.db.models.query.QuerySet.bulk_update\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">bulk_update()</span></code></a> pour réduire le nombre de requêtes SQL. Étant donné une liste ou un résultat de requête d’objets :</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"n\">entries</span> <span class=\"o\">=</span> <span class=\"n\">Entry</span><span class=\"o\">.</span><span class=\"n\">objects</span><span class=\"o\">.</span><span class=\"n\">bulk_create</span><span class=\"p\">(</span>\n    <span class=\"p\">[</span>\n        <span class=\"n\">Entry</span><span class=\"p\">(</span><span class=\"n\">headline</span><span class=\"o\">=</span><span class=\"s2\">&quot;This is a test&quot;</span><span class=\"p\">),</span>\n        <span class=\"n\">Entry</span><span class=\"p\">(</span><span class=\"n\">headline</span><span class=\"o\">=</span><span class=\"s2\">&quot;This is only a test&quot;</span><span class=\"p\">),</span>\n    <span class=\"p\">]</span>\n<span class=\"p\">)</span>\n</code></pre></div>\n<p>L’exemple suivant :</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"n\">entries</span><span class=\"p\">[</span><span class=\"mi\">0</span><span class=\"p\">]</span><span class=\"o\">.</span><span class=\"n\">headline</span> <span class=\"o\">=</span> <span class=\"s2\">&quot;This is not a test&quot;</span>\n<span class=\"n\">entries</span><span class=\"p\">[</span><span class=\"mi\">1</span><span class=\"p\">]</span><span class=\"o\">.</span><span class=\"n\">headline</span> <span class=\"o\">=</span> <span class=\"s2\">&quot;This is no longer a test&quot;</span>\n<span class=\"n\">Entry</span><span class=\"o\">.</span><span class=\"n\">objects</span><span class=\"o\">.</span><span class=\"n\">bulk_update</span><span class=\"p\">(</span><span class=\"n\">entries</span><span class=\"p\">,</span> <span class=\"p\">[</span><span class=\"s2\">&quot;headline&quot;</span><span class=\"p\">])</span>\n</code></pre></div>\n<p>…est préférable à :</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"n\">entries</span><span class=\"p\">[</span><span class=\"mi\">0</span><span class=\"p\">]</span><span class=\"o\">.</span><span class=\"n\">headline</span> <span class=\"o\">=</span> <span class=\"s2\">&quot;This is not a test&quot;</span>\n<span class=\"n\">entries</span><span class=\"p\">[</span><span class=\"mi\">0</span><span class=\"p\">]</span><span class=\"o\">.</span><span class=\"n\">save</span><span class=\"p\">()</span>\n<span class=\"n\">entries</span><span class=\"p\">[</span><span class=\"mi\">1</span><span class=\"p\">]</span><span class=\"o\">.</span><span class=\"n\">headline</span> <span class=\"o\">=</span> <span class=\"s2\">&quot;This is no longer a test&quot;</span>\n<span class=\"n\">entries</span><span class=\"p\">[</span><span class=\"mi\">1</span><span class=\"p\">]</span><span class=\"o\">.</span><span class=\"n\">save</span><span class=\"p\">()</span>\n</code></pre></div>\n<p>Note that <a class=\"reference internal\" href=\"/fr/6.1/ref/models/querysets/#django.db.models.query.QuerySet.bulk_update\" title=\"django.db.models.query.QuerySet.bulk_update\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">bulk_update()</span></code></a> has several\ncaveats, so ensure it’s appropriate for your use case.</p>\n</section>\n<section id=\"insert-in-bulk\">\n<h3>Insertion groupée<a class=\"heading-anchor\" href=\"#insert-in-bulk\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Lors de l’insertion d’objets dans des champs <a class=\"reference internal\" href=\"/fr/6.1/ref/models/fields/#django.db.models.ManyToManyField\" title=\"django.db.models.ManyToManyField\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">ManyToManyField</span></code></a>, utilisez <a class=\"reference internal\" href=\"/fr/6.1/ref/models/relations/#django.db.models.fields.related.RelatedManager.add\" title=\"django.db.models.fields.related.RelatedManager.add\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">add()</span></code></a> avec plusieurs objets pour réduire le nombre de requêtes SQL. Par exemple</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"n\">my_band</span><span class=\"o\">.</span><span class=\"n\">members</span><span class=\"o\">.</span><span class=\"n\">add</span><span class=\"p\">(</span><span class=\"n\">me</span><span class=\"p\">,</span> <span class=\"n\">my_friend</span><span class=\"p\">)</span>\n</code></pre></div>\n<p>…est préférable à :</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"n\">my_band</span><span class=\"o\">.</span><span class=\"n\">members</span><span class=\"o\">.</span><span class=\"n\">add</span><span class=\"p\">(</span><span class=\"n\">me</span><span class=\"p\">)</span>\n<span class=\"n\">my_band</span><span class=\"o\">.</span><span class=\"n\">members</span><span class=\"o\">.</span><span class=\"n\">add</span><span class=\"p\">(</span><span class=\"n\">my_friend</span><span class=\"p\">)</span>\n</code></pre></div>\n<p>…où <code class=\"docutils literal notranslate\"><span class=\"pre\">Band</span></code> et <code class=\"docutils literal notranslate\"><span class=\"pre\">Artist</span></code> sont des modèles liés par une relation plusieurs-à-plusieurs.</p>\n<p>Lors de l’insertion de plusieurs paires d’objets dans des champs <a class=\"reference internal\" href=\"/fr/6.1/ref/models/fields/#django.db.models.ManyToManyField\" title=\"django.db.models.ManyToManyField\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">ManyToManyField</span></code></a> ou lorsque la table personnalisée <a class=\"reference internal\" href=\"/fr/6.1/ref/models/fields/#django.db.models.ManyToManyField.through\" title=\"django.db.models.ManyToManyField.through\"><code class=\"xref py py-attr docutils literal notranslate\"><span class=\"pre\">through</span></code></a> est définie, utilisez la méthode <a class=\"reference internal\" href=\"/fr/6.1/ref/models/querysets/#django.db.models.query.QuerySet.bulk_create\" title=\"django.db.models.query.QuerySet.bulk_create\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">bulk_create()</span></code></a> pour réduire le nombre de requêtes SQL. Par exemple</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"n\">PizzaToppingRelationship</span> <span class=\"o\">=</span> <span class=\"n\">Pizza</span><span class=\"o\">.</span><span class=\"n\">toppings</span><span class=\"o\">.</span><span class=\"n\">through</span>\n<span class=\"n\">PizzaToppingRelationship</span><span class=\"o\">.</span><span class=\"n\">objects</span><span class=\"o\">.</span><span class=\"n\">bulk_create</span><span class=\"p\">(</span>\n    <span class=\"p\">[</span>\n        <span class=\"n\">PizzaToppingRelationship</span><span class=\"p\">(</span><span class=\"n\">pizza</span><span class=\"o\">=</span><span class=\"n\">my_pizza</span><span class=\"p\">,</span> <span class=\"n\">topping</span><span class=\"o\">=</span><span class=\"n\">pepperoni</span><span class=\"p\">),</span>\n        <span class=\"n\">PizzaToppingRelationship</span><span class=\"p\">(</span><span class=\"n\">pizza</span><span class=\"o\">=</span><span class=\"n\">your_pizza</span><span class=\"p\">,</span> <span class=\"n\">topping</span><span class=\"o\">=</span><span class=\"n\">pepperoni</span><span class=\"p\">),</span>\n        <span class=\"n\">PizzaToppingRelationship</span><span class=\"p\">(</span><span class=\"n\">pizza</span><span class=\"o\">=</span><span class=\"n\">your_pizza</span><span class=\"p\">,</span> <span class=\"n\">topping</span><span class=\"o\">=</span><span class=\"n\">mushroom</span><span class=\"p\">),</span>\n    <span class=\"p\">],</span>\n    <span class=\"n\">ignore_conflicts</span><span class=\"o\">=</span><span class=\"kc\">True</span><span class=\"p\">,</span>\n<span class=\"p\">)</span>\n</code></pre></div>\n<p>…est préférable à :</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"n\">my_pizza</span><span class=\"o\">.</span><span class=\"n\">toppings</span><span class=\"o\">.</span><span class=\"n\">add</span><span class=\"p\">(</span><span class=\"n\">pepperoni</span><span class=\"p\">)</span>\n<span class=\"n\">your_pizza</span><span class=\"o\">.</span><span class=\"n\">toppings</span><span class=\"o\">.</span><span class=\"n\">add</span><span class=\"p\">(</span><span class=\"n\">pepperoni</span><span class=\"p\">,</span> <span class=\"n\">mushroom</span><span class=\"p\">)</span>\n</code></pre></div>\n<p>…où <code class=\"docutils literal notranslate\"><span class=\"pre\">Pizza</span></code> et <code class=\"docutils literal notranslate\"><span class=\"pre\">Topping</span></code> ont une relation plusieurs-à-plusieurs. Notez qu’il existe un certain nombre de <a class=\"reference internal\" href=\"/fr/6.1/ref/models/querysets/#django.db.models.query.QuerySet.bulk_create\" title=\"django.db.models.query.QuerySet.bulk_create\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">restrictions</span> <span class=\"pre\">à</span> <span class=\"pre\">cette</span> <span class=\"pre\">méthode</span></code></a>, il s’agit donc de s’assurer qu’elle correspond à votre cas d’utilisation.</p>\n</section>\n<section id=\"remove-in-bulk\">\n<h3>Suppression groupée<a class=\"heading-anchor\" href=\"#remove-in-bulk\"><span class=\"visually-hidden\">Lien vers cette rubrique</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Lors de la suppression d’objets de champs <a class=\"reference internal\" href=\"/fr/6.1/ref/models/fields/#django.db.models.ManyToManyField\" title=\"django.db.models.ManyToManyField\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">ManyToManyField</span></code></a>, utilisez <a class=\"reference internal\" href=\"/fr/6.1/ref/models/relations/#django.db.models.fields.related.RelatedManager.remove\" title=\"django.db.models.fields.related.RelatedManager.remove\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">remove()</span></code></a> avec plusieurs objets pour réduire le nombre de requêtes SQL. Par exemple</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"n\">my_band</span><span class=\"o\">.</span><span class=\"n\">members</span><span class=\"o\">.</span><span class=\"n\">remove</span><span class=\"p\">(</span><span class=\"n\">me</span><span class=\"p\">,</span> <span class=\"n\">my_friend</span><span class=\"p\">)</span>\n</code></pre></div>\n<p>…est préférable à :</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"n\">my_band</span><span class=\"o\">.</span><span class=\"n\">members</span><span class=\"o\">.</span><span class=\"n\">remove</span><span class=\"p\">(</span><span class=\"n\">me</span><span class=\"p\">)</span>\n<span class=\"n\">my_band</span><span class=\"o\">.</span><span class=\"n\">members</span><span class=\"o\">.</span><span class=\"n\">remove</span><span class=\"p\">(</span><span class=\"n\">my_friend</span><span class=\"p\">)</span>\n</code></pre></div>\n<p>…où <code class=\"docutils literal notranslate\"><span class=\"pre\">Band</span></code> et <code class=\"docutils literal notranslate\"><span class=\"pre\">Artist</span></code> sont des modèles liés par une relation plusieurs-à-plusieurs.</p>\n<p>When removing multiple many-to-many relationships involving several instances\nof the related models, use the <a class=\"reference internal\" href=\"/fr/6.1/ref/models/querysets/#django.db.models.query.QuerySet.delete\" title=\"django.db.models.query.QuerySet.delete\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">delete()</span></code></a>\nmethod on a filtered queryset of the field’s\n<a class=\"reference internal\" href=\"/fr/6.1/ref/models/fields/#django.db.models.ManyToManyField.through\" title=\"django.db.models.ManyToManyField.through\"><code class=\"xref py py-attr docutils literal notranslate\"><span class=\"pre\">through</span></code></a> model. By combining multiple\nconditions with <a class=\"reference internal\" href=\"/fr/6.1/ref/models/querysets/#q-objects\"><span class=\"std std-ref\">Objets Q()</span></a>, you can delete several relationships in a\nsingle query. For example:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.db.models</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">Q</span>\n\n<span class=\"n\">PizzaToppingRelationship</span> <span class=\"o\">=</span> <span class=\"n\">Pizza</span><span class=\"o\">.</span><span class=\"n\">toppings</span><span class=\"o\">.</span><span class=\"n\">through</span>\n<span class=\"n\">PizzaToppingRelationship</span><span class=\"o\">.</span><span class=\"n\">objects</span><span class=\"o\">.</span><span class=\"n\">filter</span><span class=\"p\">(</span>\n    <span class=\"n\">Q</span><span class=\"p\">(</span><span class=\"n\">pizza</span><span class=\"o\">=</span><span class=\"n\">my_pizza</span><span class=\"p\">,</span> <span class=\"n\">topping</span><span class=\"o\">=</span><span class=\"n\">pepperoni</span><span class=\"p\">)</span>\n    <span class=\"o\">|</span> <span class=\"n\">Q</span><span class=\"p\">(</span><span class=\"n\">pizza</span><span class=\"o\">=</span><span class=\"n\">your_pizza</span><span class=\"p\">,</span> <span class=\"n\">topping</span><span class=\"o\">=</span><span class=\"n\">pepperoni</span><span class=\"p\">)</span>\n    <span class=\"o\">|</span> <span class=\"n\">Q</span><span class=\"p\">(</span><span class=\"n\">pizza</span><span class=\"o\">=</span><span class=\"n\">your_pizza</span><span class=\"p\">,</span> <span class=\"n\">topping</span><span class=\"o\">=</span><span class=\"n\">mushroom</span><span class=\"p\">)</span>\n<span class=\"p\">)</span><span class=\"o\">.</span><span class=\"n\">delete</span><span class=\"p\">()</span>\n</code></pre></div>\n<p>…est préférable à :</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"n\">my_pizza</span><span class=\"o\">.</span><span class=\"n\">toppings</span><span class=\"o\">.</span><span class=\"n\">remove</span><span class=\"p\">(</span><span class=\"n\">pepperoni</span><span class=\"p\">)</span>\n<span class=\"n\">your_pizza</span><span class=\"o\">.</span><span class=\"n\">toppings</span><span class=\"o\">.</span><span class=\"n\">remove</span><span class=\"p\">(</span><span class=\"n\">pepperoni</span><span class=\"p\">,</span> <span class=\"n\">mushroom</span><span class=\"p\">)</span>\n</code></pre></div>\n<p>…où <code class=\"docutils literal notranslate\"><span class=\"pre\">Pizza</span></code> et <code class=\"docutils literal notranslate\"><span class=\"pre\">Topping</span></code> sont liés par une relation plusieurs-à-plusieurs.</p>\n</section>\n</section>","rootId":"database-access-optimization","toc":[{"title":"Priorité au profilage","anchor":"profile-first","children":[]},{"title":"Techniques standards d’optimisation de base de données","anchor":"use-standard-db-optimization-techniques","children":[]},{"title":"Compréhension des objets QuerySet","anchor":"understand-querysets","children":[{"title":"Compréhension de l’évaluation du QuerySet","anchor":"understand-queryset-evaluation","children":[]},{"title":"Compréhension des attributs mis en cache","anchor":"understand-cached-attributes","children":[]},{"title":"Utilisation de la balise de gabarit with","anchor":"use-the-with-template-tag","children":[]},{"title":"Utilisation de iterator()","anchor":"use-iterator","children":[]},{"title":"Utilisation de explain()","anchor":"use-explain","children":[]}]},{"title":"Travail de base de données en base de données plutôt qu’en Python","anchor":"do-database-work-in-the-database-rather-than-in-python","children":[{"title":"Utilisation de RawSQL","anchor":"use-rawsql","children":[]},{"title":"Utilisation de SQL brut","anchor":"use-raw-sql","children":[]}]},{"title":"Sélection d’objets individuels en utilisant une colonne unique et indexée","anchor":"retrieve-individual-objects-using-a-unique-indexed-column","children":[]},{"title":"Retrieve related objects efficiently","anchor":"retrieve-related-objects-efficiently","children":[{"title":"Use the FETCH_PEERS fetch mode","anchor":"use-the-fetch-peers-fetch-mode","children":[]},{"title":"Utilisation de QuerySet.select_related() et prefetch_related()","anchor":"use-queryset-select-related-and-prefetch-related","children":[]},{"title":"Use prefetch_related_objects()","anchor":"use-prefetch-related-objects","children":[]}]},{"title":"Ne pas récupérer des éléments inutilement","anchor":"don-t-retrieve-things-you-don-t-need","children":[{"title":"Utilisation de QuerySet.values() et values_list()","anchor":"use-queryset-values-and-values-list","children":[]},{"title":"Utilisation de QuerySet.defer() et only()","anchor":"use-queryset-defer-and-only","children":[]},{"title":"Utilisation de QuerySet.contains(obj)","anchor":"use-queryset-contains-obj","children":[]},{"title":"Utilisation de QuerySet.count()","anchor":"use-queryset-count","children":[]},{"title":"Utilisation de QuerySet.exists()","anchor":"use-queryset-exists","children":[]},{"title":"Ne pas abuser de contains(), count() et exists()","anchor":"don-t-overuse-contains-count-and-exists","children":[]},{"title":"Utilisation de QuerySet.update() et delete()","anchor":"use-queryset-update-and-delete","children":[]},{"title":"Utilisation directe de valeurs de clé étrangère","anchor":"use-foreign-key-values-directly","children":[]},{"title":"Ne pas trier les résultats sans raison","anchor":"don-t-order-results-if-you-don-t-care","children":[]}]},{"title":"Utiliser les méthodes d’opérations groupées","anchor":"use-bulk-methods","children":[{"title":"Création groupée","anchor":"create-in-bulk","children":[]},{"title":"Mise à jour groupée","anchor":"update-in-bulk","children":[]},{"title":"Insertion groupée","anchor":"insert-in-bulk","children":[]},{"title":"Suppression groupée","anchor":"remove-in-bulk","children":[]}]}],"breadcrumbs":[{"docname":"topics/index","title":"Utilisation de Django","url":"/fr/6.1/topics/"},{"docname":"topics/db/index","title":"Modèles et bases de données","url":"/fr/6.1/topics/db/"}],"prev":{"docname":"topics/db/tablespaces","title":"Espaces de tables","url":"/fr/6.1/topics/db/tablespaces/"},"next":{"docname":"topics/db/instrumentation","title":"Instrumentation de base de données","url":"/fr/6.1/topics/db/instrumentation/"},"formats":{"html":"/fr/6.1/topics/db/optimization/","markdown":"/fr/6.1/topics/db/optimization.md","json":"/fr/6.1/topics/db/optimization.json"},"source":"https://github.com/django/django/blob/stable/6.1.x/docs/topics/db/optimization.txt","official":"https://docs.djangoproject.com/fr/6.1/topics/db/optimization/","inVersions":["6.1","6.0","5.2","5.1","5.0","4.2","4.1","4.0","3.2","3.1","3.0","2.2","2.1","2.0","1.11","1.10","1.9"],"inLocales":["en","sv","zh-hans","ga","fr","ja","id","it","pt-br","ko","es","el","pl"]}