{"title":"データベースアクセスの最適化","version":"5.2","locale":"ja","docname":"topics/db/optimization","url":"/ja/5.2/topics/db/optimization/","canonical":"https://djangodocs.dev/ja/5.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/5.2/faq/models/#faq-see-raw-sql-queries\"><span class=\"std std-ref\">どんなクエリを実行しているか、それにどれくらいのコストがかかっているかを確認してください</span></a> 。特定の <code class=\"docutils literal notranslate\"><span class=\"pre\">QuerySet</span></code> がデータベースによってどのように実行されるのかを理解するには、 <a class=\"reference internal\" href=\"/ja/5.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\"><span class=\"pre\">QuerySet.explain()</span></code></a> を使用してください。また、 <a class=\"extlink-pypi reference external\" href=\"https://pypi.org/project/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/5.2/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> や <a class=\"reference internal\" href=\"/ja/5.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\"><span class=\"pre\">Field.db_index</span></code></a> を使用します。 <a class=\"reference internal\" href=\"/ja/5.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\"><span class=\"pre\">filter()</span></code></a> 、 <a class=\"reference internal\" href=\"/ja/5.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\"><span class=\"pre\">exclude()</span></code></a> 、 <a class=\"reference internal\" href=\"/ja/5.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\"><span class=\"pre\">order_by()</span></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/5.2/topics/cache/\"><span class=\"doc\">汎用キャッシュ</span></a> のような高コストな最適化手法については説明しません。</p>\n</section>\n<section id=\"understand-querysets\">\n<h2><code class=\"docutils literal notranslate\"><span class=\"pre\">QuerySet</span></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/5.2/ref/models/querysets/\"><span class=\"doc\">QuerySet</span></a> を理解することは、シンプルなコードでパフォーマンスを上げるために極めて重要です。特に:</p>\n<section id=\"understand-queryset-evaluation\">\n<h3><code class=\"docutils literal notranslate\"><span class=\"pre\">QuerySet</span></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/5.2/topics/db/queries/#querysets-are-lazy\"><span class=\"std std-ref\">QuerySet は遅延評価される</span></a> こと。</p></li>\n<li><p><a class=\"reference internal\" href=\"/ja/5.2/ref/models/querysets/#when-querysets-are-evaluated\"><span class=\"std std-ref\">いつQuerySet が評価されるのか</span></a> 。</p></li>\n<li><p>どのように <a class=\"reference internal\" href=\"/ja/5.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>クエリセット全体のキャッシュだけでなく、ORM オブジェクトの属性の結果のキャッシュもあります。通常、呼び出し可能でない属性はキャッシュされます。例えば、<a class=\"reference internal\" href=\"/ja/5.2/topics/db/queries/#queryset-model-example\"><span class=\"std std-ref\">例のブログモデル</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>しかし、一般に、呼び出し可能な属性は毎回DBルックアップを引き起こします:</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>テンプレート上のコードを読む際には注意が必要です。テンプレートシステムは括弧を許容していませんが、呼び出し可能なオブジェクトは自動的に呼び出されるので、上記の区別が隠れてしまいます。</p>\n<p>独自のプロパティにも注意が必要です - 必要なときにキャッシングを実装するのはあなた次第です。たとえば <a class=\"reference internal\" href=\"/ja/5.2/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><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\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p><code class=\"docutils literal notranslate\"><span class=\"pre\">QuerySet</span></code> のキャッシュ処理を活用するため、<a class=\"reference internal\" href=\"/ja/5.2/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><code class=\"docutils literal notranslate\"><span class=\"pre\">iterator()</span></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\"><span class=\"pre\">QuerySet</span></code> のキャッシュ動作に多くのメモリが使われる可能性があります。この場合、<a class=\"reference internal\" href=\"/ja/5.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\"><span class=\"pre\">iterator()</span></code></a> が有用です。</p>\n</section>\n<section id=\"use-explain\">\n<h3><code class=\"docutils literal notranslate\"><span class=\"pre\">explain()</span></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/5.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\"><span class=\"pre\">QuerySet.explain()</span></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/5.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/5.2/ref/models/expressions/#django.db.models.F\" title=\"django.db.models.F\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">F</span> <span class=\"pre\">式</span></code></a> を使い、同一モデル内で他のフィールドに基づくフィルタリングを行います。</p></li>\n<li><p><a class=\"reference internal\" href=\"/ja/5.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\"><span class=\"pre\">RawSQL</span></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/5.2/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> 表現です。これにより、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/5.2/topics/db/sql/\"><span class=\"doc\">モデルの取り出しおよび書き込みをするためのカスタム SQL</span></a> を記述します。<code class=\"docutils literal notranslate\"><span class=\"pre\">django.db.connection.queries</span></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/5.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\"><span class=\"pre\">get()</span></code></a> を使用する際に、<a class=\"reference internal\" href=\"/ja/5.2/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> や <a class=\"reference internal\" href=\"/ja/5.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\"><span class=\"pre\">db_index</span></code></a> を持つカラムを使用する理由は2つあります。まず、データベースインデックスによりクエリが高速になります。また、ルックアップに一致するオブジェクトが複数ある場合、クエリは非常に遅くなる可能性があります。カラムに一意の制約を持つことで、これが決して起こらないことが保証されます。</p>\n<p>例えば、<a class=\"reference internal\" href=\"/ja/5.2/topics/db/queries/#queryset-model-example\"><span class=\"std std-ref\">例のブログモデル</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>上記は以下よりも高速です:</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>これは、<code class=\"docutils literal notranslate\"><span class=\"pre\">id</span></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><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>まず第一に、<code class=\"docutils literal notranslate\"><span class=\"pre\">headline</span></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\"><span class=\"pre\">QuerySet.select_related()</span></code> や <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\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p><a class=\"reference internal\" href=\"/ja/5.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\"><span class=\"pre\">select_related()</span></code></a> と <a class=\"reference internal\" href=\"/ja/5.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\"><span class=\"pre\">prefetch_related()</span></code></a> を徹底的に理解し、使用してください:</p>\n<ul class=\"simple\">\n<li><p>必要に応じて、<a class=\"reference internal\" href=\"/ja/5.2/topics/db/managers/\"><span class=\"doc\">マネージャとデフォルトマネージャ</span></a> の中で。マネージャが使用されているときと使用されていないときに注意してください; 誤りやすい部分なので、思い込みのないようにしてください。</p></li>\n<li><p>ビューのコードや他のレイヤーの中で。必要に応じて <a class=\"reference internal\" href=\"/ja/5.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\"><span class=\"pre\">prefetch_related_objects()</span></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\"><span class=\"pre\">QuerySet.values()</span></code> や <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\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>単に値の <code class=\"docutils literal notranslate\"><span class=\"pre\">dict</span></code> や <code class=\"docutils literal notranslate\"><span class=\"pre\">list</span></code> がほしいだけで ORM モデルオブジェクトが必要ないときは、<a class=\"reference internal\" href=\"/ja/5.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\"><span class=\"pre\">values()</span></code></a> を適切に使用してください。テンプレートのコード内で、モデルオブジェクトを置き換えるのに役立ちます - 辞書がテンプレートで使われているものと同じ属性を持っている限り問題ありません。</p>\n</section>\n<section id=\"use-queryset-defer-and-only\">\n<h3><code class=\"docutils literal notranslate\"><span class=\"pre\">QuerySet.defer()</span></code> や <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\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>データベースに不要な(もしくはほとんど必要とされない)列がある場合は、それらを読み込むことを防ぐために、 <a class=\"reference internal\" href=\"/ja/5.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\"><span class=\"pre\">defer()</span></code></a> や <a class=\"reference internal\" href=\"/ja/5.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\"><span class=\"pre\">only()</span></code></a> を使用します。もし除外した列を <em>使用する</em> 場合、ORMは異なるクエリでそれらを取得する必要があるため、不適切な使用はパフォーマンスの低下を招くことに注意してください。</p>\n<p>プロファイリングなしに、あまり積極的にフィールドの遅延を行わないようにしてください。たとえ、いくつかのカラムしか使用しないことになったとしても、データベースは結果の1行のために、非テキスト、非 <code class=\"docutils literal notranslate\"><span class=\"pre\">VARCHAR</span></code> データのほとんどをディスクから読み込まなければならないからです。 <code class=\"docutils literal notranslate\"><span class=\"pre\">defer()</span></code> と <code class=\"docutils literal notranslate\"><span class=\"pre\">only()</span></code> メソッドは、多くのテキストデータの読み込みを避けられる場合や、Python に戻すのに多くの処理が必要なフィールドに対して最も有効なメソッドです。いつものように、まずはプロファイルを作成し、次に最適化を行ってください。</p>\n</section>\n<section id=\"use-queryset-contains-obj\">\n<h3><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\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>...単に <code class=\"docutils literal notranslate\"><span class=\"pre\">obj</span></code> がクエリセットに存在するかどうかを知りたいだけなら、 <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><code class=\"docutils literal notranslate\"><span class=\"pre\">QuerySet.count()</span></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\"><span class=\"pre\">len(queryset)</span></code> よりも適切です。</p>\n</section>\n<section id=\"use-queryset-exists\">\n<h3><code class=\"docutils literal notranslate\"><span class=\"pre\">QuerySet.exists()</span></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\"><span class=\"pre\">if</span> <span class=\"pre\">queryset</span></code> よりも適切です。</p>\n<p>しかし:</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\"><span class=\"pre\">contains()</span></code> 、 <code class=\"docutils literal notranslate\"><span class=\"pre\">count()</span></code> 、 <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\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>もしクエリセットの他のデータが必要になったときは、すぐに評価を行います。</p>\n<p>例えば、 <code class=\"docutils literal notranslate\"><span class=\"pre\">User</span></code> と多対多の関連をもつ <code class=\"docutils literal notranslate\"><span class=\"pre\">Group</span></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><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>最適である理由:</p>\n<ol class=\"arabic simple\">\n<li><p>クエリセットは遅延評価されるので、 <code class=\"docutils literal notranslate\"><span class=\"pre\">display_group_members</span></code> が <code class=\"docutils literal notranslate\"><span class=\"pre\">False</span></code> の場合、データベースクエリは発行されない</p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">members</span></code> 変数に <code class=\"docutils literal notranslate\"><span class=\"pre\">group.members.all()</span></code> を格納することで、クエリ結果のキャッシュを再利用できる。</p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">if</span> <span class=\"pre\">members:</span></code> の行は <code class=\"docutils literal notranslate\"><span class=\"pre\">QuerySet.__bool__()</span></code> を呼び出すことになり、その結果、データベースで <code class=\"docutils literal notranslate\"><span class=\"pre\">group.members.all()</span></code> クエリが実行される。もし結果が無ければ <code class=\"docutils literal notranslate\"><span class=\"pre\">False</span></code> を返し、結果があれば <code class=\"docutils literal notranslate\"><span class=\"pre\">True</span></code> を返す。</p></li>\n<li><p><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> の行は、結果のキャッシュにユーザーが含まれるかどうかを確認するので、新たなデータベースクエリは発行されない。</p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">len(members)</span></code> を使用することで <code class=\"docutils literal notranslate\"><span class=\"pre\">QuerySet.__len__()</span></code> が呼び出される。このとき、結果のキャッシュが再利用されるので、新たなデータベースクエリは発行されない。</p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">for</span> <span class=\"pre\">member</span></code> は結果のキャッシュを繰り返し処理する。</p></li>\n</ol>\n<p>このコードは合計で、データベースクエリを1回または0回実行します。ここで行った唯一の意図的な最適化は、 <code class=\"docutils literal notranslate\"><span class=\"pre\">members</span></code> 変数を使用することです。もし <code class=\"docutils literal notranslate\"><span class=\"pre\">if</span></code> に対して <code class=\"docutils literal notranslate\"><span class=\"pre\">QuerySet.exists()</span></code> を使用したり、<code class=\"docutils literal notranslate\"><span class=\"pre\">in</span></code> に対して <code class=\"docutils literal notranslate\"><span class=\"pre\">QuerySet.contains()</span></code> を使用したり、<code class=\"docutils literal notranslate\"><span class=\"pre\">count</span></code> に対して <code class=\"docutils literal notranslate\"><span class=\"pre\">QuerySet.count()</span></code> を使用したりした場合、それぞれ追加のクエリが発生します。</p>\n</section>\n<section id=\"use-queryset-update-and-delete\">\n<h3><code class=\"docutils literal notranslate\"><span class=\"pre\">QuerySet.update()</span></code> や <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\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>複数のオブジェクトを読み込んで値を設定し、それらを個別に保存するのではなく、<a class=\"reference internal\" href=\"/ja/5.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/5.2/topics/db/queries/#topics-db-queries-delete\"><span class=\"std std-ref\">一括削除</span></a> を使用してください。</p>\n<p>ただし、これらの一括更新メソッドは、個々のインスタンスの <code class=\"docutils literal notranslate\"><span class=\"pre\">save()</span></code> や <code class=\"docutils literal notranslate\"><span class=\"pre\">delete()</span></code> メソッドを呼び出すことはできないので、通常のデータベースオブジェクト <a class=\"reference internal\" href=\"/ja/5.2/ref/signals/\"><span class=\"doc\">シグナル</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><span class=\"n\">entry</span><span class=\"o\">.</span><span class=\"n\">blog_id</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><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>気にならないなら結果を並べ替えない<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/5.2/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>) があり、それが不要な場合は、パラメータなしで <a class=\"reference internal\" href=\"/ja/5.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\"><span class=\"pre\">order_by()</span></code></a> を呼び出すことで <code class=\"docutils literal notranslate\"><span class=\"pre\">QuerySet</span></code> からそれを削除します。</p>\n<p>データベースにインデックスを追加すると、並べ替えのパフォーマンスが向上する可能性があります。</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文の数を減らすために一括（bulk）メソッドを使用する</p>\n<section id=\"create-in-bulk\">\n<h3>一括で作成する<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/5.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\"><span class=\"pre\">bulk_create()</span></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=\"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>...これは下記よりも適切です:</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><a class=\"reference internal\" href=\"/ja/5.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\"><span class=\"pre\">このメソッド</span></code></a> には多くの注意事項があるので、自分のユースケースに適切であることを確認してください。</p>\n</section>\n<section id=\"update-in-bulk\">\n<h3>一括で更新する<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/5.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\"><span class=\"pre\">bulk_create()</span></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=\"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>以下のような例を考えます:</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>...これは下記よりも適切です:</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><a class=\"reference internal\" href=\"/ja/5.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\"><span class=\"pre\">このメソッド</span></code></a> には多くの注意事項があるので、自分のユースケースに適切であることを確認してください。</p>\n</section>\n<section id=\"insert-in-bulk\">\n<h3>一括で挿入する<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><a class=\"reference internal\" href=\"/ja/5.2/ref/models/fields/#django.db.models.ManyToManyField\" title=\"django.db.models.ManyToManyField\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">ManyToManyFields</span></code></a> にオブジェクトを追加するとき、可能であれば <a class=\"reference internal\" href=\"/ja/5.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\"><span class=\"pre\">add()</span></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=\"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>...これは下記よりも適切です:</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>……ここで、 <code class=\"docutils literal notranslate\"><span class=\"pre\">Band</span></code> と <code class=\"docutils literal notranslate\"><span class=\"pre\">Artist</span></code> は多対多のリレーションシップを持つモデル同士です。</p>\n<p><a class=\"reference internal\" href=\"/ja/5.2/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> に異なるオブジェクトのペアを挿入する場合、またはカスタムの <a class=\"reference internal\" href=\"/ja/5.2/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> テーブルが定義されている場合は、SQLクエリの数を減らすために <a class=\"reference internal\" href=\"/ja/5.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\"><span class=\"pre\">bulk_create()</span></code></a> メソッドを使用します。例えば以下のようにします：</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>...これは下記よりも適切です:</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>ここで、 <code class=\"docutils literal notranslate\"><span class=\"pre\">Pizza</span></code> と <code class=\"docutils literal notranslate\"><span class=\"pre\">Topping</span></code> は多対多の関連を持っています。<a class=\"reference internal\" href=\"/ja/5.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\"><span class=\"pre\">このメソッド</span></code></a> には多くの注意事項があるので、自分のユースケースに適切であることを確認してください。</p>\n</section>\n<section id=\"remove-in-bulk\">\n<h3>一括で削除する<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/5.2/ref/models/fields/#django.db.models.ManyToManyField\" title=\"django.db.models.ManyToManyField\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">ManyToManyFields</span></code></a> からオブジェクトを取り除くとき、可能であれば <a class=\"reference internal\" href=\"/ja/5.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\"><span class=\"pre\">remove()</span></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=\"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>...これは下記よりも適切です:</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>……ここで、 <code class=\"docutils literal notranslate\"><span class=\"pre\">Band</span></code> と <code class=\"docutils literal notranslate\"><span class=\"pre\">Artist</span></code> は多対多のリレーションシップを持つモデル同士です。</p>\n<p><a class=\"reference internal\" href=\"/ja/5.2/ref/models/fields/#django.db.models.ManyToManyField\" title=\"django.db.models.ManyToManyField\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">ManyToManyFields</span></code></a> から異なるペアのオブジェクトを取り除くとき、複数の <a class=\"reference internal\" href=\"/ja/5.2/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> モデルインスタンスと <a class=\"reference internal\" href=\"/ja/5.2/ref/models/querysets/#django.db.models.Q\" title=\"django.db.models.Q\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">Q</span></code></a> 式を用いて、 <a class=\"reference internal\" href=\"/ja/5.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\"><span class=\"pre\">delete()</span></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=\"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>...これは下記よりも適切です:</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>... ここで、 <code class=\"docutils literal notranslate\"><span class=\"pre\">Pizza</span></code> と <code class=\"docutils literal notranslate\"><span class=\"pre\">Topping</span></code> は多対多の関係です。</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":"一括で作成する","anchor":"create-in-bulk","children":[]},{"title":"一括で更新する","anchor":"update-in-bulk","children":[]},{"title":"一括で挿入する","anchor":"insert-in-bulk","children":[]},{"title":"一括で削除する","anchor":"remove-in-bulk","children":[]}]}],"breadcrumbs":[{"docname":"topics/index","title":"Django を使う","url":"/ja/5.2/topics/"},{"docname":"topics/db/index","title":"モデルとデータベース","url":"/ja/5.2/topics/db/"}],"prev":{"docname":"topics/db/tablespaces","title":"テーブル空間（tablespace）","url":"/ja/5.2/topics/db/tablespaces/"},"next":{"docname":"topics/db/instrumentation","title":"データベースの計測","url":"/ja/5.2/topics/db/instrumentation/"},"formats":{"html":"/ja/5.2/topics/db/optimization/","markdown":"/ja/5.2/topics/db/optimization.md","json":"/ja/5.2/topics/db/optimization.json"},"source":"https://github.com/django/django/blob/stable/5.2.x/docs/topics/db/optimization.txt","official":"https://docs.djangoproject.com/ja/5.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","sv","zh-hans","ga","fr","ja","id","it","pt-br","ko","es","el","pl"]}