{"title":"データベースアクセスの最適化","version":"4.2","locale":"ja","docname":"topics/db/optimization","url":"/ja/4.2/topics/db/optimization/","canonical":"https://djangodocs.dev/ja/4.2/topics/db/optimization/","summary":"Djangoのデータベース層は、開発者がデータベースを最大限活用できるように、さまざまな方法を提供しています。","html":"<h1>データベースアクセスの最適化<a class=\"heading-anchor\" href=\"#database-access-optimization\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h1>\n<p>Djangoのデータベース層は、開発者がデータベースを最大限活用できるように、さまざまな方法を提供しています。このドキュメントでは、データベースアクセスを最適化する際にとるべき手順を、大まかにいくつかの見出しとしてまとめています。それぞれの見出しの下に、関連するドキュメントへのリンクを集約した上で、さまざまなヒントを追加しています。</p>\n<section id=\"profile-first\">\n<h2>まずはプロファイルを取る<a class=\"heading-anchor\" href=\"#profile-first\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>一般的なプログラミング手法と同様に、これは言うまでもないことです。<a class=\"reference internal\" href=\"/ja/4.2/faq/models/#faq-see-raw-sql-queries\"><span class=\"std std-ref\">どんなクエリを実行し何がコストなのか</span></a> を判別してください。<a class=\"reference internal\" href=\"/ja/4.2/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\">QuerySet.explain()</code></a> を使用し、データベース上で特定の <code class=\"docutils literal notranslate\">QuerySet</code> がどのように実行されるかを理解してください。また、<a class=\"reference external\" href=\"https://github.com/jazzband/django-debug-toolbar/\">django-debug-toolbar</a> といった外部のプロジェクトや、データベースを直接監視するツールを使うのもいいでしょう。</p>\n<p>要件に従って、速度またはメモリ、およびその両方を最適化することができます。片方を最適化することは、もう片方に悪影響を及ぼすことがありますが、互いに助けになることもあります。また、データベースプロセスによって行われる処理と Python のプロセスによる処理は (あなたにとって) 必ずしも同等のコストとはなりません。その優先順位とバランスを決めるのはあなた自身です。そして、その設計はアプリケーションやサーバーに依存するため、要求通りに設計するのもあなたの仕事です。</p>\n<p>以下で紹介する項目すべてにおいて、あらゆる変更の後に忘れずに分析を行い、施した変更が有益だったこと、およびその恩恵が可読性の低下を十分上回ることを確認してください。以下の <strong>すべて</strong> の提案において、一般的な原則があなたの状況に当てはまらない可能性があること、それどころか逆効果になりかねない可能性さえあることに十分注意してください。</p>\n</section>\n<section id=\"use-standard-db-optimization-techniques\">\n<h2>標準的な DB 最適化のテクニックを使う<a class=\"heading-anchor\" href=\"#use-standard-db-optimization-techniques\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>以下のようなものが上げられます:</p>\n<ul class=\"simple\">\n<li><p><a class=\"reference external\" href=\"https://en.wikipedia.org/wiki/Database_index\">Indexes</a>. プロファイリングでどのようなインデックスを追加すべきかを決定した <em>後に</em> 、最優先事項として行うべきことです。Djangoからインデックスを追加するには、 <a class=\"reference internal\" href=\"/ja/4.2/ref/models/options/#django.db.models.Options.indexes\" title=\"django.db.models.Options.indexes\"><code class=\"xref py py-attr docutils literal notranslate\">Meta.indexes</code></a> や <a class=\"reference internal\" href=\"/ja/4.2/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\">Field.db_index</code></a> を使用します。 <a class=\"reference internal\" href=\"/ja/4.2/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\">filter()</code></a> 、 <a class=\"reference internal\" href=\"/ja/4.2/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\">exclude()</code></a> 、 <a class=\"reference internal\" href=\"/ja/4.2/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\">order_by()</code></a> などで頻繁に参照するフィールドにインデックスを追加することで、参照を高速化させることができるかもしれません。ただし、最適なインデックスの決定は、各個のアプリケーションのデータベースに依存する複雑な問題であることに留意してください。インデックスを維持するためのオーバーヘッドは、クエリの高速化によるメリットよりも大きいかもしれません。</p></li>\n</ul>\n<ul class=\"simple\">\n<li><p>フィールドタイプの適切な使用。</p></li>\n</ul>\n<p>以降は、上記の明確な対処は実行済みだという前提で進めていきます。このドキュメントの残りの部分では、不要な作業をしなくて済むように、Django をどのように使えばいいかを中心に説明します。またこのドキュメントでは、<a class=\"reference internal\" href=\"/ja/4.2/topics/cache/\"><span class=\"doc\">汎用キャッシュ</span></a> のような高コストな最適化手法については説明しません。</p>\n</section>\n<section id=\"understand-querysets\">\n<h2><code class=\"docutils literal notranslate\">QuerySet</code> を理解する<a class=\"heading-anchor\" href=\"#understand-querysets\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p><a class=\"reference internal\" href=\"/ja/4.2/ref/models/querysets/\"><span class=\"doc\">QuerySet</span></a> を理解することは、シンプルなコードでパフォーマンスを上げるために極めて重要です。特に:</p>\n<section id=\"understand-queryset-evaluation\">\n<h3><code class=\"docutils literal notranslate\">QuerySet</code> の評価を理解する<a class=\"heading-anchor\" href=\"#understand-queryset-evaluation\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>パフォーマンスの問題を回避するには、以下を理解することが重要です:</p>\n<ul class=\"simple\">\n<li><p><a class=\"reference internal\" href=\"/ja/4.2/topics/db/queries/#querysets-are-lazy\"><span class=\"std std-ref\">QuerySet は lazy</span></a> であること。</p></li>\n<li><p>いつ <span class=\"xref std std-ref\">QuerySet</span> が評価されるのか &lt;when-querysets-are-evaluated&gt;`。</p></li>\n<li><p>どのように <a class=\"reference internal\" href=\"/ja/4.2/topics/db/queries/#caching-and-querysets\"><span class=\"std std-ref\">データがメモリ上に保持されるか</span></a>。</p></li>\n</ul>\n</section>\n<section id=\"understand-cached-attributes\">\n<h3>キャッシュされる属性を理解する<a class=\"heading-anchor\" href=\"#understand-cached-attributes\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>As well as caching of the whole <code class=\"docutils literal notranslate\">QuerySet</code>, there is caching of the result of\nattributes on ORM objects. In general, attributes that are not callable will be\ncached. For example, assuming the <a class=\"reference internal\" href=\"/ja/4.2/topics/db/queries/#queryset-model-example\"><span class=\"std std-ref\">example blog models</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>entry <span class=\"o\">=</span> Entry<span class=\"o\">.</span>objects<span class=\"o\">.</span>get<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>entry<span class=\"o\">.</span>blog  <span class=\"c1\"># Blog object is retrieved at this point</span>\n<span class=\"gp\">&gt;&gt;&gt; </span>entry<span class=\"o\">.</span>blog  <span class=\"c1\"># cached version, no DB access</span>\n</code></pre></div>\n<p>But in general, callable attributes cause DB lookups every time:</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>entry <span class=\"o\">=</span> Entry<span class=\"o\">.</span>objects<span class=\"o\">.</span>get<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>entry<span class=\"o\">.</span>authors<span class=\"o\">.</span>all<span class=\"p\">()</span>  <span class=\"c1\"># query performed</span>\n<span class=\"gp\">&gt;&gt;&gt; </span>entry<span class=\"o\">.</span>authors<span class=\"o\">.</span>all<span class=\"p\">()</span>  <span class=\"c1\"># query performed again</span>\n</code></pre></div>\n<p>テンプレート上のコードを読む際には注意が必要です - テンプレートシステムは括弧を許容していませんが、呼び出し可能なオブジェクトは自動的に呼び出されるので、上記の区別が隠れてしまいます。</p>\n<p>独自のプロパティにも注意が必要です - 必要なときにキャッシングを実装するのはあなた次第です。たとえば <a class=\"reference internal\" href=\"/ja/4.2/ref/utils/#django.utils.functional.cached_property\" title=\"django.utils.functional.cached_property\"><code class=\"xref py py-class docutils literal notranslate\">cached_property</code></a> デコレータを使用します。</p>\n</section>\n<section id=\"use-the-with-template-tag\">\n<h3><code class=\"docutils literal notranslate\">with</code> テンプレートタグを使用する<a class=\"heading-anchor\" href=\"#use-the-with-template-tag\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p><code class=\"docutils literal notranslate\">QuerySet</code> のキャッシング処理を活用するため、<a class=\"reference internal\" href=\"/ja/4.2/ref/templates/builtins/#std-templatetag-with\"><code class=\"xref std std-ttag docutils literal notranslate\">with</code></a> テンプレートタグの使用が推奨されます。</p>\n</section>\n<section id=\"use-iterator\">\n<h3><code class=\"docutils literal notranslate\">iterator()</code> を使用する<a class=\"heading-anchor\" href=\"#use-iterator\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>多くのオブジェクトを扱う際には、<code class=\"docutils literal notranslate\">QuerySet</code> のキャッシング動作に多くのメモリが使われる可能性があります。この場合、<a class=\"reference internal\" href=\"/ja/4.2/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\">iterator()</code></a> が有用です。</p>\n</section>\n<section id=\"use-explain\">\n<h3><code class=\"docutils literal notranslate\">explain()</code> を使用する<a class=\"heading-anchor\" href=\"#use-explain\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p><a class=\"reference internal\" href=\"/ja/4.2/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\">QuerySet.explain()</code></a> を使うと、使用されているインデックスや結合など、データベースがクエリをどのように実行しているのか、詳細な情報を得られます。この詳細情報は、より効率的になるようにクエリを書き換えたり、パフォーマンスを向上させるために追加できるインデックスを特定するのに役立ちます。</p>\n</section>\n</section>\n<section id=\"do-database-work-in-the-database-rather-than-in-python\">\n<h2>データベースの仕事を Python ではなくデータベースに行わせる<a class=\"heading-anchor\" href=\"#do-database-work-in-the-database-rather-than-in-python\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>例えば:</p>\n<ul class=\"simple\">\n<li><p>最も基本的なレベルでは、<a class=\"reference internal\" href=\"/ja/4.2/ref/models/querysets/#queryset-api\"><span class=\"std std-ref\">filter や exclude</span></a> を使ってデータベース内でフィルタリングを行います。</p></li>\n<li><p><a class=\"reference internal\" href=\"/ja/4.2/ref/models/expressions/#django.db.models.F\" title=\"django.db.models.F\"><code class=\"xref py py-class docutils literal notranslate\">F expressions</code></a> を使い、同一モデル内で他のフィールドに基づくフィルタリングを行います。</p></li>\n<li><p><a class=\"reference internal\" href=\"/ja/4.2/topics/db/aggregation/\"><span class=\"doc\">データベース内の集計をするためアノテーション</span></a> を使います。</p></li>\n</ul>\n<p>必要な SQL を生成するのに不十分な場合は:</p>\n<section id=\"use-rawsql\">\n<h3><code class=\"docutils literal notranslate\">RawSQL</code> を使用する<a class=\"heading-anchor\" href=\"#use-rawsql\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>保守性は高くありませんが、より強力な方法は <a class=\"reference internal\" href=\"/ja/4.2/ref/models/expressions/#django.db.models.expressions.RawSQL\" title=\"django.db.models.expressions.RawSQL\"><code class=\"xref py py-class docutils literal notranslate\">RawSQL</code></a> 表現です。これにより、SQL を明示的にクエリに追加することができます。これでもまだ不十分な場合は:</p>\n</section>\n<section id=\"use-raw-sql\">\n<h3>素の SQL を使用する<a class=\"heading-anchor\" href=\"#use-raw-sql\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p><a class=\"reference internal\" href=\"/ja/4.2/topics/db/sql/\"><span class=\"doc\">モデルの取り出しおよび書き込みをするための独自の SQL</span></a> を記述します。<code class=\"docutils literal notranslate\">django.db.connection.queries</code> を使い、Django があなたのために何を書いているのかを理解して、それを元に始めてください。</p>\n</section>\n</section>\n<section id=\"retrieve-individual-objects-using-a-unique-indexed-column\">\n<h2>ユニークかつインデックス済みの列を使用して個別のオブジェクトを取得する<a class=\"heading-anchor\" href=\"#retrieve-individual-objects-using-a-unique-indexed-column\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p><a class=\"reference internal\" href=\"/ja/4.2/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\">get()</code></a> を使って個別オブジェクトを取得する際に、<a class=\"reference internal\" href=\"/ja/4.2/ref/models/fields/#django.db.models.Field.unique\" title=\"django.db.models.Field.unique\"><code class=\"xref py py-attr docutils literal notranslate\">unique</code></a> や <a class=\"reference internal\" href=\"/ja/4.2/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\">db_index</code></a> が設定された列を使用するのには 2 つの理由があります。1 つは、データベースインデックスにより受け里が高速になるからです。加えて、複数のオブジェクトが検索にマッチするとクエリは遅くなります; 列にユニーク制限をかけることでこれを完全に防ぐことができます。</p>\n<p>So using the <a class=\"reference internal\" href=\"/ja/4.2/topics/db/queries/#queryset-model-example\"><span class=\"std std-ref\">example blog models</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>entry <span class=\"o\">=</span> Entry<span class=\"o\">.</span>objects<span class=\"o\">.</span>get<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>上記は以下よりも高速です:</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>entry <span class=\"o\">=</span> Entry<span class=\"o\">.</span>objects<span class=\"o\">.</span>get<span class=\"p\">(</span>headline<span class=\"o\">=</span><span class=\"s2\">&quot;News Item Title&quot;</span><span class=\"p\">)</span>\n</code></pre></div>\n<p>これは、<code class=\"docutils literal notranslate\">id</code> がデータベースによってインデックス化されていて、ユニークだと保証されているからです。</p>\n<p>以下のようにすると非常に遅くなる恐れがあります:</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>entry <span class=\"o\">=</span> Entry<span class=\"o\">.</span>objects<span class=\"o\">.</span>get<span class=\"p\">(</span>headline__startswith<span class=\"o\">=</span><span class=\"s2\">&quot;News&quot;</span><span class=\"p\">)</span>\n</code></pre></div>\n<p>まず第一に、<code class=\"docutils literal notranslate\">headline</code> はインデックス化されておらず、データベースのデータ取り出しを遅くします。</p>\n<p>そして第二に、この検索では単一のオブジェクトが返されることは保証されません。クエリが 1 つ以上のオブジェクトと一致する場合、すべてのオブジェクトをデータベースから取り出して転送します。この余分な負荷は、100 とか 1000 といった多量のレコードが返されるときには相当な量になります。データベースが複数のサーバーによって構成される場合、ネットワークのオーバーヘッドと待ち時間が発生するため、この負荷はさらに大きくなります。</p>\n</section>\n<section id=\"retrieve-everything-at-once-if-you-know-you-will-need-it\">\n<h2>必要なものが分かっているときは一度にすべてを取り出す<a class=\"heading-anchor\" href=\"#retrieve-everything-at-once-if-you-know-you-will-need-it\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>すべての部分を必要とする単一のデータセットの異なる部分に対してデータベースを何度もヒットするのは、一般的に、1 つのクエリですべてを取得するよりも非効率です。 これは、1 つのクエリだけが必要なときにループ内でクエリを実行し、その結果何度もデータベースクエリを実行することになってしまう場合に、特に重要となります。そこで:</p>\n<section id=\"use-queryset-select-related-and-prefetch-related\">\n<h3><code class=\"docutils literal notranslate\">QuerySet.select_related()</code> や <code class=\"docutils literal notranslate\">prefetch_related()</code> を使用する<a class=\"heading-anchor\" href=\"#use-queryset-select-related-and-prefetch-related\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p><a class=\"reference internal\" href=\"/ja/4.2/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\">select_related()</code></a> と <a class=\"reference internal\" href=\"/ja/4.2/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\">prefetch_related()</code></a> を徹底的に理解し、使用してください:</p>\n<ul class=\"simple\">\n<li><p>必要に応じて、<a class=\"reference internal\" href=\"/ja/4.2/topics/db/managers/\"><span class=\"doc\">マネージャとデフォルトマネージャ</span></a> の中で。マネージャが使用されているときと使用されていないときに注意してください; 誤りやすい部分なので、思い込みのないようにしてください。</p></li>\n<li><p>ビューのコードや他のレイヤーの中で。必要に応じて <a class=\"reference internal\" href=\"/ja/4.2/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\">prefetch_related_objects()</code></a> が利用できます。</p></li>\n</ul>\n</section>\n</section>\n<section id=\"don-t-retrieve-things-you-don-t-need\">\n<h2>必要ないものを取り出さない<a class=\"heading-anchor\" href=\"#don-t-retrieve-things-you-don-t-need\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<section id=\"use-queryset-values-and-values-list\">\n<h3><code class=\"docutils literal notranslate\">QuerySet.values()</code> や <code class=\"docutils literal notranslate\">values_list()</code> を使用する<a class=\"heading-anchor\" href=\"#use-queryset-values-and-values-list\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>単に値の <code class=\"docutils literal notranslate\">dict</code> や <code class=\"docutils literal notranslate\">list</code> がほしいだけで ORM モデルオブジェクトが必要ないときは、<a class=\"reference internal\" href=\"/ja/4.2/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\">values()</code></a> を適切に使用してください。テンプレートのコード内で、モデルオブジェクトを置き換えるのに役立ちます - 辞書がテンプレートで使われているものと同じ属性を持っている限り問題ありません。</p>\n</section>\n<section id=\"use-queryset-defer-and-only\">\n<h3><code class=\"docutils literal notranslate\">QuerySet.defer()</code> や <code class=\"docutils literal notranslate\">only()</code> を使用する<a class=\"heading-anchor\" href=\"#use-queryset-defer-and-only\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>データベースに使用しない(もしくはほとんど使用されない)列がある場合は、それらを読み込むことを防ぐために、 <a class=\"reference internal\" href=\"/ja/4.2/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\">defer()</code></a> や <a class=\"reference internal\" href=\"/ja/4.2/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\">only()</code></a> を使用してください。もし除外した列を <em>使用する</em> 場合、ORMは異なるクエリでそれらを取得する必要があるため、不適切な使用は悲観的な結果を招くに注意してください。</p>\n<p>プロファイリングなしに、あまり積極的にフィールドの遅延を行わないようにしてください。たとえ、いくつかのカラムしか使用しないことになったとしても、データベースは結果の1行のために、非テキスト、非 <code class=\"docutils literal notranslate\">VARCHAR</code> データのほとんどをディスクから読み込まなければならないからです。 <code class=\"docutils literal notranslate\">defer()</code> と <code class=\"docutils literal notranslate\">only()</code> メソッドは、多くのテキストデータの読み込みを避けられる場合や、Python に戻すのに多くの処理が必要なフィールドに対して最も有効なメソッドです。いつものように、まずはプロファイルを作成し、次に最適化を行ってください。</p>\n</section>\n<section id=\"use-queryset-contains-obj\">\n<h3><code class=\"docutils literal notranslate\">QuerySet.contains(obj)</code> を使用する<a class=\"heading-anchor\" href=\"#use-queryset-contains-obj\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>...単に <code class=\"docutils literal notranslate\">obj</code> がクエリセットに存在するかどうかを知りたいだけなら、 <code class=\"docutils literal notranslate\">if obj in queryset</code> よりも適切です。</p>\n</section>\n<section id=\"use-queryset-count\">\n<h3><code class=\"docutils literal notranslate\">QuerySet.count()</code> を使用する<a class=\"heading-anchor\" href=\"#use-queryset-count\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>...単に数を知りたいだけなら、 <code class=\"docutils literal notranslate\">len(queryset)</code> よりも適切です。</p>\n</section>\n<section id=\"use-queryset-exists\">\n<h3><code class=\"docutils literal notranslate\">QuerySet.exists()</code> を使用する<a class=\"heading-anchor\" href=\"#use-queryset-exists\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>...単に1つ以上の結果が存在するかどうかを知りたいだけなら、 <code class=\"docutils literal notranslate\">if queryset</code> よりも適切です。</p>\n<p>But:</p>\n</section>\n<section id=\"don-t-overuse-contains-count-and-exists\">\n<span id=\"overuse-of-count-and-exists\"></span><h3><code class=\"docutils literal notranslate\">contains()</code> 、 <code class=\"docutils literal notranslate\">count()</code> 、 <code class=\"docutils literal notranslate\">exists()</code> を使いすぎない<a class=\"heading-anchor\" href=\"#don-t-overuse-contains-count-and-exists\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>もしクエリセットの他のデータが必要になったときは、すぐに評価を行います。</p>\n<p>例えば、 <code class=\"docutils literal notranslate\">User</code> と多対多の関連をもつ <code class=\"docutils literal notranslate\">Group</code> モデルを考えたとき、以下のコードが最適です:</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>members <span class=\"o\">=</span> group<span class=\"o\">.</span>members<span class=\"o\">.</span>all<span class=\"p\">()</span>\n\n<span class=\"k\">if</span> display_group_members<span class=\"p\">:</span>\n    <span class=\"k\">if</span> members<span class=\"p\">:</span>\n        <span class=\"k\">if</span> current_user <span class=\"ow\">in</span> members<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>members<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>members<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> member <span class=\"ow\">in</span> members<span class=\"p\">:</span>\n            <span class=\"nb\">print</span><span class=\"p\">(</span>member<span class=\"o\">.</span>username<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>最適である理由:</p>\n<ol class=\"arabic simple\">\n<li><p>クエリセットは遅延評価されるので、 <code class=\"docutils literal notranslate\">display_group_members</code> が <code class=\"docutils literal notranslate\">False</code> の場合、データベースクエリは発行されない</p></li>\n<li><p><code class=\"docutils literal notranslate\">members</code> 変数に <code class=\"docutils literal notranslate\">group.members.all()</code> を格納することで、クエリ結果のキャッシュを再利用できる。</p></li>\n<li><p><code class=\"docutils literal notranslate\">if members:</code> の行は <code class=\"docutils literal notranslate\">QuerySet.__bool__()</code> を呼び出すことになり、これはデータベースで <code class=\"docutils literal notranslate\">group.members.all()</code> のクエリが処理されることになる。もし結果が得られない場合、 <code class=\"docutils literal notranslate\">False</code> を返され、そうでない場合は <code class=\"docutils literal notranslate\">True</code> が返される。</p></li>\n<li><p><code class=\"docutils literal notranslate\">if current_user in members:</code> の行は、結果のキャッシュにユーザーが含まれるかどうかを確認するので、新たなデータベースクエリは発行されない。</p></li>\n<li><p><code class=\"docutils literal notranslate\">len(members)</code> を使用することで <code class=\"docutils literal notranslate\">QuerySet.__len__()</code> が呼び出される。このとき、結果のキャッシュが再利用されるので、新たなデータベースクエリは発行されない。</p></li>\n<li><p><code class=\"docutils literal notranslate\">for member</code> は結果のキャッシュを繰り返し処理する。</p></li>\n</ol>\n<p>まとめると、このコードで発行されるデータベースクエリは0個または1個です。意図的なクエリの最適化は <code class=\"docutils literal notranslate\">members</code> 変数の使用のみです。 <code class=\"docutils literal notranslate\">if</code> に対して <code class=\"docutils literal notranslate\">QuerySet.exists()</code> を、 <code class=\"docutils literal notranslate\">in</code> に対して <code class=\"docutils literal notranslate\">QuerySet.contains()</code> を、カウントに <code class=\"docutils literal notranslate\">QuerySet.count()</code> を使うことで、それぞれに追加のクエリが発生します。</p>\n</section>\n<section id=\"use-queryset-update-and-delete\">\n<h3><code class=\"docutils literal notranslate\">QuerySet.update()</code> や <code class=\"docutils literal notranslate\">delete()</code> を使用する<a class=\"heading-anchor\" href=\"#use-queryset-update-and-delete\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>複数のオブジェクトを読み込んで値を設定し、それらを個別に保存するのではなく、<a class=\"reference internal\" href=\"/ja/4.2/topics/db/queries/#topics-db-queries-update\"><span class=\"std std-ref\">QuerySet.update()</span></a> を用いてSQLの一括UPDATE文を使用してください。同様に、可能であれば <a class=\"reference internal\" href=\"/ja/4.2/topics/db/queries/#topics-db-queries-delete\"><span class=\"std std-ref\">一括削除</span></a> を使用してください。</p>\n<p>ただし、これらの一括更新メソッドは、個々のインスタンスの <code class=\"docutils literal notranslate\">save()</code> や <code class=\"docutils literal notranslate\">delete()</code> メソッドを呼び出すことはできないので、通常のデータベースオブジェクト <a class=\"reference internal\" href=\"/ja/4.2/ref/signals/\"><span class=\"doc\">signals</span></a> に由来するものを含め、これらのメソッドに追加した独自の処理が実行されないことに注意してください。</p>\n</section>\n<section id=\"use-foreign-key-values-directly\">\n<h3>外部キーの値を直接使用する<a class=\"heading-anchor\" href=\"#use-foreign-key-values-directly\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>外部キーの値だけが必要な場合は、関連するオブジェクト全体を取得してその主キーを取るのではなく、既に持っているオブジェクトにある外部キーの値を使います。つまり、次のようにします:</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>entry<span class=\"o\">.</span>blog_id\n</code></pre></div>\n<p>代わりに、次のようにします:</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>entry<span class=\"o\">.</span>blog<span class=\"o\">.</span>id\n</code></pre></div>\n</section>\n<section id=\"don-t-order-results-if-you-don-t-care\">\n<h3>気にならないなら結果を並べ替えない<a class=\"heading-anchor\" href=\"#don-t-order-results-if-you-don-t-care\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>並び替えは無償ではありません。並び替える各フィールドは、データベースが処理しなくてはならない操作です。もしモデルに既定の順序付け (<a class=\"reference internal\" href=\"/ja/4.2/ref/models/options/#django.db.models.Options.ordering\" title=\"django.db.models.Options.ordering\"><code class=\"xref py py-attr docutils literal notranslate\">Meta.ordering</code></a>) があって、それが必要ない場合は、<a class=\"reference internal\" href=\"/ja/4.2/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\">order_by()</code></a> をパラメータなしで呼び出し、 <code class=\"docutils literal notranslate\">QuerySet</code> でそれを除去してください。</p>\n<p>Adding an index to your database may help to improve ordering performance.</p>\n</section>\n</section>\n<section id=\"use-bulk-methods\">\n<h2>一括メソッドを使用する<a class=\"heading-anchor\" href=\"#use-bulk-methods\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>SQL文の数を減らすために一括メソッドを使用する</p>\n<section id=\"create-in-bulk\">\n<h3>Create in bulk<a class=\"heading-anchor\" href=\"#create-in-bulk\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>オブジェクトを作成するとき、可能であれば <a class=\"reference internal\" href=\"/ja/4.2/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\">bulk_create()</code></a> を呼び出し、SQL文の数を減らしてください。例えば:</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>Entry<span class=\"o\">.</span>objects<span class=\"o\">.</span>bulk_create<span class=\"p\">(</span>\n    <span class=\"p\">[</span>\n        Entry<span class=\"p\">(</span>headline<span class=\"o\">=</span><span class=\"s2\">&quot;This is a test&quot;</span><span class=\"p\">),</span>\n        Entry<span class=\"p\">(</span>headline<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>...は、これよりも適切です:</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>Entry<span class=\"o\">.</span>objects<span class=\"o\">.</span>create<span class=\"p\">(</span>headline<span class=\"o\">=</span><span class=\"s2\">&quot;This is a test&quot;</span><span class=\"p\">)</span>\nEntry<span class=\"o\">.</span>objects<span class=\"o\">.</span>create<span class=\"p\">(</span>headline<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><a class=\"reference internal\" href=\"/ja/4.2/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\">このメソッド</code></a> には多くの注意事項があるので、自分のユースケースに適切であることを確認してください。</p>\n</section>\n<section id=\"update-in-bulk\">\n<h3>Update in bulk<a class=\"heading-anchor\" href=\"#update-in-bulk\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>オブジェクトを更新するとき、可能であれば <a class=\"reference internal\" href=\"/ja/4.2/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\">bulk_create()</code></a> を呼び出し、SQL文の数を減らしてください。次のようなオブジェクトのリストまたはクエリセットを考えます:</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>entries <span class=\"o\">=</span> Entry<span class=\"o\">.</span>objects<span class=\"o\">.</span>bulk_create<span class=\"p\">(</span>\n    <span class=\"p\">[</span>\n        Entry<span class=\"p\">(</span>headline<span class=\"o\">=</span><span class=\"s2\">&quot;This is a test&quot;</span><span class=\"p\">),</span>\n        Entry<span class=\"p\">(</span>headline<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>以下のような例を考えます:</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>entries<span class=\"p\">[</span><span class=\"mi\">0</span><span class=\"p\">]</span><span class=\"o\">.</span>headline <span class=\"o\">=</span> <span class=\"s2\">&quot;This is not a test&quot;</span>\nentries<span class=\"p\">[</span><span class=\"mi\">1</span><span class=\"p\">]</span><span class=\"o\">.</span>headline <span class=\"o\">=</span> <span class=\"s2\">&quot;This is no longer a test&quot;</span>\nEntry<span class=\"o\">.</span>objects<span class=\"o\">.</span>bulk_update<span class=\"p\">(</span>entries<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>...は、これよりも適切です:</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>entries<span class=\"p\">[</span><span class=\"mi\">0</span><span class=\"p\">]</span><span class=\"o\">.</span>headline <span class=\"o\">=</span> <span class=\"s2\">&quot;This is not a test&quot;</span>\nentries<span class=\"p\">[</span><span class=\"mi\">0</span><span class=\"p\">]</span><span class=\"o\">.</span>save<span class=\"p\">()</span>\nentries<span class=\"p\">[</span><span class=\"mi\">1</span><span class=\"p\">]</span><span class=\"o\">.</span>headline <span class=\"o\">=</span> <span class=\"s2\">&quot;This is no longer a test&quot;</span>\nentries<span class=\"p\">[</span><span class=\"mi\">1</span><span class=\"p\">]</span><span class=\"o\">.</span>save<span class=\"p\">()</span>\n</code></pre></div>\n<p><a class=\"reference internal\" href=\"/ja/4.2/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\">このメソッド</code></a> には多くの注意事項があるので、自分のユースケースに適切であることを確認してください。</p>\n</section>\n<section id=\"insert-in-bulk\">\n<h3>Insert in bulk<a class=\"heading-anchor\" href=\"#insert-in-bulk\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>When inserting objects into <a class=\"reference internal\" href=\"/ja/4.2/ref/models/fields/#django.db.models.ManyToManyField\" title=\"django.db.models.ManyToManyField\"><code class=\"xref py py-class docutils literal notranslate\">ManyToManyFields</code></a>, use\n<a class=\"reference internal\" href=\"/ja/4.2/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\">add()</code></a> with multiple\nobjects to reduce the number of SQL queries. 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>my_band<span class=\"o\">.</span>members<span class=\"o\">.</span>add<span class=\"p\">(</span>me<span class=\"p\">,</span> my_friend<span class=\"p\">)</span>\n</code></pre></div>\n<p>...は、これよりも適切です:</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>my_band<span class=\"o\">.</span>members<span class=\"o\">.</span>add<span class=\"p\">(</span>me<span class=\"p\">)</span>\nmy_band<span class=\"o\">.</span>members<span class=\"o\">.</span>add<span class=\"p\">(</span>my_friend<span class=\"p\">)</span>\n</code></pre></div>\n<p>...where <code class=\"docutils literal notranslate\">Bands</code> and <code class=\"docutils literal notranslate\">Artists</code> have a many-to-many relationship.</p>\n<p><a class=\"reference internal\" href=\"/ja/4.2/ref/models/fields/#django.db.models.ManyToManyField\" title=\"django.db.models.ManyToManyField\"><code class=\"xref py py-class docutils literal notranslate\">ManyToManyFields</code></a> から異なるペアのオブジェクトを追加するとき、複数の <a class=\"reference internal\" href=\"/ja/4.2/ref/models/fields/#django.db.models.ManyToManyField.through\" title=\"django.db.models.ManyToManyField.through\"><code class=\"xref py py-attr docutils literal notranslate\">through</code></a> モデルインスタンスと <a class=\"reference internal\" href=\"/ja/4.2/ref/models/querysets/#django.db.models.Q\" title=\"django.db.models.Q\"><code class=\"xref py py-class docutils literal notranslate\">Q</code></a> 式を用いて、 <a class=\"reference internal\" href=\"/ja/4.2/ref/models/querysets/#django.db.models.query.QuerySet.create\" title=\"django.db.models.query.QuerySet.create\"><code class=\"xref py py-meth docutils literal notranslate\">create()</code></a> を呼び出し、SQL文の数を減らしてください。例えば:</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>PizzaToppingRelationship <span class=\"o\">=</span> Pizza<span class=\"o\">.</span>toppings<span class=\"o\">.</span>through\nPizzaToppingRelationship<span class=\"o\">.</span>objects<span class=\"o\">.</span>bulk_create<span class=\"p\">(</span>\n    <span class=\"p\">[</span>\n        PizzaToppingRelationship<span class=\"p\">(</span>pizza<span class=\"o\">=</span>my_pizza<span class=\"p\">,</span> topping<span class=\"o\">=</span>pepperoni<span class=\"p\">),</span>\n        PizzaToppingRelationship<span class=\"p\">(</span>pizza<span class=\"o\">=</span>your_pizza<span class=\"p\">,</span> topping<span class=\"o\">=</span>pepperoni<span class=\"p\">),</span>\n        PizzaToppingRelationship<span class=\"p\">(</span>pizza<span class=\"o\">=</span>your_pizza<span class=\"p\">,</span> topping<span class=\"o\">=</span>mushroom<span class=\"p\">),</span>\n    <span class=\"p\">],</span>\n    ignore_conflicts<span class=\"o\">=</span><span class=\"kc\">True</span><span class=\"p\">,</span>\n<span class=\"p\">)</span>\n</code></pre></div>\n<p>...は、これよりも適切です:</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>my_pizza<span class=\"o\">.</span>toppings<span class=\"o\">.</span>add<span class=\"p\">(</span>pepperoni<span class=\"p\">)</span>\nyour_pizza<span class=\"o\">.</span>toppings<span class=\"o\">.</span>add<span class=\"p\">(</span>pepperoni<span class=\"p\">,</span> mushroom<span class=\"p\">)</span>\n</code></pre></div>\n<p>ここで、 <code class=\"docutils literal notranslate\">Pizza</code> と <code class=\"docutils literal notranslate\">Topping</code> は多対多の関連を持っています。<a class=\"reference internal\" href=\"/ja/4.2/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\">このメソッド</code></a> には多くの注意事項があるので、自分のユースケースに適切であることを確認してください。</p>\n</section>\n<section id=\"remove-in-bulk\">\n<h3>Remove in bulk<a class=\"heading-anchor\" href=\"#remove-in-bulk\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p><a class=\"reference internal\" href=\"/ja/4.2/ref/models/fields/#django.db.models.ManyToManyField\" title=\"django.db.models.ManyToManyField\"><code class=\"xref py py-class docutils literal notranslate\">ManyToManyFields</code></a> からオブジェクトを取り除くするとき、可能であれば <a class=\"reference internal\" href=\"/ja/4.2/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\">remove()</code></a> を呼び出し、SQL文の数を減らしてください。例えば:</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>my_band<span class=\"o\">.</span>members<span class=\"o\">.</span>remove<span class=\"p\">(</span>me<span class=\"p\">,</span> my_friend<span class=\"p\">)</span>\n</code></pre></div>\n<p>...は、これよりも適切です:</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>my_band<span class=\"o\">.</span>members<span class=\"o\">.</span>remove<span class=\"p\">(</span>me<span class=\"p\">)</span>\nmy_band<span class=\"o\">.</span>members<span class=\"o\">.</span>remove<span class=\"p\">(</span>my_friend<span class=\"p\">)</span>\n</code></pre></div>\n<p>...where <code class=\"docutils literal notranslate\">Bands</code> and <code class=\"docutils literal notranslate\">Artists</code> have a many-to-many relationship.</p>\n<p><a class=\"reference internal\" href=\"/ja/4.2/ref/models/fields/#django.db.models.ManyToManyField\" title=\"django.db.models.ManyToManyField\"><code class=\"xref py py-class docutils literal notranslate\">ManyToManyFields</code></a> から異なるペアのオブジェクトを取り除くとき、複数の <a class=\"reference internal\" href=\"/ja/4.2/ref/models/fields/#django.db.models.ManyToManyField.through\" title=\"django.db.models.ManyToManyField.through\"><code class=\"xref py py-attr docutils literal notranslate\">through</code></a> モデルインスタンスと <a class=\"reference internal\" href=\"/ja/4.2/ref/models/querysets/#django.db.models.Q\" title=\"django.db.models.Q\"><code class=\"xref py py-class docutils literal notranslate\">Q</code></a> 式を用いて、 <a class=\"reference internal\" href=\"/ja/4.2/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\">delete()</code></a> を呼び出し、SQL文の数を減らしてください。例えば:</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=\"nn\">django.db.models</span> <span class=\"kn\">import</span> Q\n\nPizzaToppingRelationship <span class=\"o\">=</span> Pizza<span class=\"o\">.</span>toppings<span class=\"o\">.</span>through\nPizzaToppingRelationship<span class=\"o\">.</span>objects<span class=\"o\">.</span>filter<span class=\"p\">(</span>\n    Q<span class=\"p\">(</span>pizza<span class=\"o\">=</span>my_pizza<span class=\"p\">,</span> topping<span class=\"o\">=</span>pepperoni<span class=\"p\">)</span>\n    <span class=\"o\">|</span> Q<span class=\"p\">(</span>pizza<span class=\"o\">=</span>your_pizza<span class=\"p\">,</span> topping<span class=\"o\">=</span>pepperoni<span class=\"p\">)</span>\n    <span class=\"o\">|</span> Q<span class=\"p\">(</span>pizza<span class=\"o\">=</span>your_pizza<span class=\"p\">,</span> topping<span class=\"o\">=</span>mushroom<span class=\"p\">)</span>\n<span class=\"p\">)</span><span class=\"o\">.</span>delete<span class=\"p\">()</span>\n</code></pre></div>\n<p>...は、これよりも適切です:</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>my_pizza<span class=\"o\">.</span>toppings<span class=\"o\">.</span>remove<span class=\"p\">(</span>pepperoni<span class=\"p\">)</span>\nyour_pizza<span class=\"o\">.</span>toppings<span class=\"o\">.</span>remove<span class=\"p\">(</span>pepperoni<span class=\"p\">,</span> mushroom<span class=\"p\">)</span>\n</code></pre></div>\n<p>...where <code class=\"docutils literal notranslate\">Pizza</code> and <code class=\"docutils literal notranslate\">Topping</code> have a many-to-many relationship.</p>\n</section>\n</section>","rootId":"database-access-optimization","toc":[{"title":"まずはプロファイルを取る","anchor":"profile-first","children":[]},{"title":"標準的な DB 最適化のテクニックを使う","anchor":"use-standard-db-optimization-techniques","children":[]},{"title":"QuerySet を理解する","anchor":"understand-querysets","children":[{"title":"QuerySet の評価を理解する","anchor":"understand-queryset-evaluation","children":[]},{"title":"キャッシュされる属性を理解する","anchor":"understand-cached-attributes","children":[]},{"title":"with テンプレートタグを使用する","anchor":"use-the-with-template-tag","children":[]},{"title":"iterator() を使用する","anchor":"use-iterator","children":[]},{"title":"explain() を使用する","anchor":"use-explain","children":[]}]},{"title":"データベースの仕事を Python ではなくデータベースに行わせる","anchor":"do-database-work-in-the-database-rather-than-in-python","children":[{"title":"RawSQL を使用する","anchor":"use-rawsql","children":[]},{"title":"素の SQL を使用する","anchor":"use-raw-sql","children":[]}]},{"title":"ユニークかつインデックス済みの列を使用して個別のオブジェクトを取得する","anchor":"retrieve-individual-objects-using-a-unique-indexed-column","children":[]},{"title":"必要なものが分かっているときは一度にすべてを取り出す","anchor":"retrieve-everything-at-once-if-you-know-you-will-need-it","children":[{"title":"QuerySet.select_related() や prefetch_related() を使用する","anchor":"use-queryset-select-related-and-prefetch-related","children":[]}]},{"title":"必要ないものを取り出さない","anchor":"don-t-retrieve-things-you-don-t-need","children":[{"title":"QuerySet.values() や values_list() を使用する","anchor":"use-queryset-values-and-values-list","children":[]},{"title":"QuerySet.defer() や only() を使用する","anchor":"use-queryset-defer-and-only","children":[]},{"title":"QuerySet.contains(obj) を使用する","anchor":"use-queryset-contains-obj","children":[]},{"title":"QuerySet.count() を使用する","anchor":"use-queryset-count","children":[]},{"title":"QuerySet.exists() を使用する","anchor":"use-queryset-exists","children":[]},{"title":"contains() 、 count() 、 exists() を使いすぎない","anchor":"don-t-overuse-contains-count-and-exists","children":[]},{"title":"QuerySet.update() や delete() を使用する","anchor":"use-queryset-update-and-delete","children":[]},{"title":"外部キーの値を直接使用する","anchor":"use-foreign-key-values-directly","children":[]},{"title":"気にならないなら結果を並べ替えない","anchor":"don-t-order-results-if-you-don-t-care","children":[]}]},{"title":"一括メソッドを使用する","anchor":"use-bulk-methods","children":[{"title":"Create in bulk","anchor":"create-in-bulk","children":[]},{"title":"Update in bulk","anchor":"update-in-bulk","children":[]},{"title":"Insert in bulk","anchor":"insert-in-bulk","children":[]},{"title":"Remove in bulk","anchor":"remove-in-bulk","children":[]}]}],"breadcrumbs":[{"docname":"topics/index","title":"Django を使う","url":"/ja/4.2/topics/"},{"docname":"topics/db/index","title":"モデルとデータベース","url":"/ja/4.2/topics/db/"}],"prev":{"docname":"topics/db/tablespaces","title":"Tablespaces","url":"/ja/4.2/topics/db/tablespaces/"},"next":{"docname":"topics/db/instrumentation","title":"データベースの計測","url":"/ja/4.2/topics/db/instrumentation/"},"formats":{"html":"/ja/4.2/topics/db/optimization/","markdown":"/ja/4.2/topics/db/optimization.md","json":"/ja/4.2/topics/db/optimization.json"},"source":"https://github.com/django/django/blob/stable/4.2.x/docs/topics/db/optimization.txt","official":"https://docs.djangoproject.com/ja/4.2/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","zh-hans","fr","ja","id","it","pt-br","ko","es","el","pl"]}