{"title":"データベースアクセスの最適化","version":"2.1","locale":"ja","docname":"topics/db/optimization","url":"/ja/2.1/topics/db/optimization/","canonical":"https://djangodocs.dev/ja/2.1/topics/db/optimization/","summary":"Django's database layer provides various ways to help developers get the most out of their databases.","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's database layer provides various ways to help developers get the most\nout of their databases. This document gathers together links to the relevant\ndocumentation, and adds various tips, organized under a number of headings that\noutline the steps to take when attempting to optimize your database usage.</p>\n<section id=\"profile-first\">\n<h2>Profile first<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/2.1/faq/models/#faq-see-raw-sql-queries\"><span class=\"std std-ref\">どんなクエリを実行し何がコストなのか</span></a> を判別してください。<a class=\"reference internal\" href=\"/ja/2.1/ref/models/querysets/#django.db.models.query.QuerySet.explain\" title=\"django.db.models.query.QuerySet.explain\"><code class=\"xref py py-meth docutils literal notranslate\">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\">Index</a>。これは最優先事項です。ただし、どのインデックスを追加すべきか分析して決定した <em>後</em> の話しです。<a class=\"reference internal\" href=\"/ja/2.1/ref/models/fields/#django.db.models.Field.db_index\" title=\"django.db.models.Field.db_index\"><code class=\"xref py py-attr docutils literal notranslate\">Field.db_index</code></a> や <a class=\"reference internal\" href=\"/ja/2.1/ref/models/options/#django.db.models.Options.index_together\" title=\"django.db.models.Options.index_together\"><code class=\"xref py py-attr docutils literal notranslate\">Meta.index_together</code></a> を使って、Django からインデックスを追加してください。インデックスは検索の高速化に役立つので、<a class=\"reference internal\" href=\"/ja/2.1/ref/models/querysets/#django.db.models.query.QuerySet.filter\" title=\"django.db.models.query.QuerySet.filter\"><code class=\"xref py py-meth docutils literal notranslate\">filter()</code></a>、<a class=\"reference internal\" href=\"/ja/2.1/ref/models/querysets/#django.db.models.query.QuerySet.exclude\" title=\"django.db.models.query.QuerySet.exclude\"><code class=\"xref py py-meth docutils literal notranslate\">exclude()</code></a>、<a class=\"reference internal\" href=\"/ja/2.1/ref/models/querysets/#django.db.models.query.QuerySet.order_by\" title=\"django.db.models.query.QuerySet.order_by\"><code class=\"xref py py-meth docutils literal notranslate\">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/2.1/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/2.1/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/2.1/topics/db/queries/#querysets-are-lazy\"><span class=\"std std-ref\">QuerySet は lazy</span></a> であること。</p></li>\n<li><p>いつ <a class=\"reference internal\" href=\"/ja/2.1/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/2.1/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><code class=\"docutils literal notranslate\">QuerySet</code> 全体をキャッシュすることに加えて、ORM オブジェクトの属性の結果のキャッシングも存在します。通常、カラブルではない属性はキャッシュされます。例として、<a class=\"reference internal\" href=\"/ja/2.1/topics/db/queries/#queryset-model-example\"><span class=\"std std-ref\">Weblog モデルの例</span></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=\"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>その一方で、通常カラブルの属性は毎回 DB の検索を引き起こします:</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=\"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/2.1/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/2.1/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/2.1/ref/models/querysets/#django.db.models.query.QuerySet.iterator\" title=\"django.db.models.query.QuerySet.iterator\"><code class=\"xref py py-meth docutils literal notranslate\">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/2.1/ref/models/querysets/#django.db.models.query.QuerySet.explain\" title=\"django.db.models.query.QuerySet.explain\"><code class=\"xref py py-meth docutils literal notranslate\">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/2.1/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/2.1/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/2.1/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/2.1/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/2.1/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/2.1/ref/models/querysets/#django.db.models.query.QuerySet.get\" title=\"django.db.models.query.QuerySet.get\"><code class=\"xref py py-meth docutils literal notranslate\">get()</code></a> を使って個別オブジェクトを取得する際に、<a class=\"reference internal\" href=\"/ja/2.1/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/2.1/ref/models/fields/#django.db.models.Field.db_index\" title=\"django.db.models.Field.db_index\"><code class=\"xref py py-attr docutils literal notranslate\">db_index</code></a> が設定された列を使用するのには 2 つの理由があります。1 つは、データベースインデックスにより受け里が高速になるからです。加えて、複数のオブジェクトが検索にマッチするとクエリは遅くなります; 列にユニーク制限をかけることでこれを完全に防ぐことができます。</p>\n<p>したがって、<a class=\"reference internal\" href=\"/ja/2.1/topics/db/queries/#queryset-model-example\"><span class=\"std std-ref\">Weblog モデルの例</span></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=\"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=\"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=\"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=\"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=\"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/2.1/ref/models/querysets/#django.db.models.query.QuerySet.select_related\" title=\"django.db.models.query.QuerySet.select_related\"><code class=\"xref py py-meth docutils literal notranslate\">select_related()</code></a> と <a class=\"reference internal\" href=\"/ja/2.1/ref/models/querysets/#django.db.models.query.QuerySet.prefetch_related\" title=\"django.db.models.query.QuerySet.prefetch_related\"><code class=\"xref py py-meth docutils literal notranslate\">prefetch_related()</code></a> を徹底的に理解し、使用してください:</p>\n<ul class=\"simple\">\n<li><p>必要に応じて、<a class=\"reference internal\" href=\"/ja/2.1/topics/db/managers/\"><span class=\"doc\">マネージャとデフォルトマネージャ</span></a> の中で。マネージャが使用されているときと使用されていないときに注意してください; 誤りやすい部分なので、思い込みのないようにしてください。</p></li>\n<li><p>ビューのコードや他のレイヤーの中で。必要に応じて <a class=\"reference internal\" href=\"/ja/2.1/ref/models/querysets/#django.db.models.prefetch_related_objects\" title=\"django.db.models.prefetch_related_objects\"><code class=\"xref py py-func docutils literal notranslate\">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/2.1/ref/models/querysets/#django.db.models.query.QuerySet.values\" title=\"django.db.models.query.QuerySet.values\"><code class=\"xref py py-meth docutils literal notranslate\">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>Use <a class=\"reference internal\" href=\"/ja/2.1/ref/models/querysets/#django.db.models.query.QuerySet.defer\" title=\"django.db.models.query.QuerySet.defer\"><code class=\"xref py py-meth docutils literal notranslate\">defer()</code></a> and\n<a class=\"reference internal\" href=\"/ja/2.1/ref/models/querysets/#django.db.models.query.QuerySet.only\" title=\"django.db.models.query.QuerySet.only\"><code class=\"xref py py-meth docutils literal notranslate\">only()</code></a> if there are database columns\nyou know that you won't need (or won't need in most cases) to avoid loading\nthem. Note that if you <em>do</em> use them, the ORM will have to go and get them in\na separate query, making this a pessimization if you use it inappropriately.</p>\n<p>Also, be aware that there is some (small extra) overhead incurred inside\nDjango when constructing a model with deferred fields. Don't be too aggressive\nin deferring fields without profiling as the database has to read most of the\nnon-text, non-VARCHAR data from the disk for a single row in the results, even\nif it ends up only using a few columns. The <code class=\"docutils literal notranslate\">defer()</code> and <code class=\"docutils literal notranslate\">only()</code> methods\nare most useful when you can avoid loading a lot of text data or for fields\nthat might take a lot of processing to convert back to Python. As always,\nprofile first, then optimize.</p>\n</section>\n<section id=\"use-queryset-count\">\n<h3>Use <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>...if you only want the count, rather than doing <code class=\"docutils literal notranslate\">len(queryset)</code>.</p>\n</section>\n<section id=\"use-queryset-exists\">\n<h3>Use <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>...if you only want to find out if at least one result exists, rather than <code class=\"docutils literal notranslate\">if\nqueryset</code>.</p>\n<p>But:</p>\n</section>\n<section id=\"don-t-overuse-count-and-exists\">\n<span id=\"overuse-of-count-and-exists\"></span><h3>Don't overuse <code class=\"docutils literal notranslate\">count()</code> and <code class=\"docutils literal notranslate\">exists()</code><a class=\"heading-anchor\" href=\"#don-t-overuse-count-and-exists\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>If you are going to need other data from the QuerySet, just evaluate it.</p>\n<p>For example, assuming an Email model that has a <code class=\"docutils literal notranslate\">body</code> attribute and a\nmany-to-many relation to User, the following template code is optimal:</p>\n<div class=\"code-block\" data-language=\"html+django\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Django template</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=\"Django template code\"><code><span class=\"cp\">{%</span> <span class=\"k\">if</span> <span class=\"nv\">display_inbox</span> <span class=\"cp\">%}</span>\n  <span class=\"cp\">{%</span> <span class=\"k\">with</span> <span class=\"nv\">emails</span><span class=\"o\">=</span><span class=\"nv\">user.emails.all</span> <span class=\"cp\">%}</span>\n    <span class=\"cp\">{%</span> <span class=\"k\">if</span> <span class=\"nv\">emails</span> <span class=\"cp\">%}</span>\n      <span class=\"p\">&lt;</span><span class=\"nt\">p</span><span class=\"p\">&gt;</span>You have <span class=\"cp\">{{</span> <span class=\"nv\">emails</span><span class=\"o\">|</span><span class=\"nf\">length</span> <span class=\"cp\">}}</span> email(s)<span class=\"p\">&lt;/</span><span class=\"nt\">p</span><span class=\"p\">&gt;</span>\n      <span class=\"cp\">{%</span> <span class=\"k\">for</span> <span class=\"nv\">email</span> <span class=\"k\">in</span> <span class=\"nv\">emails</span> <span class=\"cp\">%}</span>\n        <span class=\"p\">&lt;</span><span class=\"nt\">p</span><span class=\"p\">&gt;</span><span class=\"cp\">{{</span> <span class=\"nv\">email.body</span> <span class=\"cp\">}}</span><span class=\"p\">&lt;/</span><span class=\"nt\">p</span><span class=\"p\">&gt;</span>\n      <span class=\"cp\">{%</span> <span class=\"k\">endfor</span> <span class=\"cp\">%}</span>\n    <span class=\"cp\">{%</span> <span class=\"k\">else</span> <span class=\"cp\">%}</span>\n      <span class=\"p\">&lt;</span><span class=\"nt\">p</span><span class=\"p\">&gt;</span>No messages today.<span class=\"p\">&lt;/</span><span class=\"nt\">p</span><span class=\"p\">&gt;</span>\n    <span class=\"cp\">{%</span> <span class=\"k\">endif</span> <span class=\"cp\">%}</span>\n  <span class=\"cp\">{%</span> <span class=\"k\">endwith</span> <span class=\"cp\">%}</span>\n<span class=\"cp\">{%</span> <span class=\"k\">endif</span> <span class=\"cp\">%}</span>\n</code></pre></div>\n<p>It is optimal because:</p>\n<ol class=\"arabic simple\">\n<li><p>Since QuerySets are lazy, this does no database queries if 'display_inbox'\nis False.</p></li>\n<li><p>Use of <a class=\"reference internal\" href=\"/ja/2.1/ref/templates/builtins/#std-templatetag-with\"><code class=\"xref std std-ttag docutils literal notranslate\">with</code></a> means that we store <code class=\"docutils literal notranslate\">user.emails.all</code> in a variable\nfor later use, allowing its cache to be re-used.</p></li>\n<li><p>The line <code class=\"docutils literal notranslate\">{% if emails %}</code> causes <code class=\"docutils literal notranslate\">QuerySet.__bool__()</code> to be called,\nwhich causes the <code class=\"docutils literal notranslate\">user.emails.all()</code> query to be run on the database, and\nat the least the first line to be turned into an ORM object. If there aren't\nany results, it will return False, otherwise True.</p></li>\n<li><p>The use of <code class=\"docutils literal notranslate\">{{ emails|length }}</code> calls <code class=\"docutils literal notranslate\">QuerySet.__len__()</code>, filling\nout the rest of the cache without doing another query.</p></li>\n<li><p>The <a class=\"reference internal\" href=\"/ja/2.1/ref/templates/builtins/#std-templatetag-for\"><code class=\"xref std std-ttag docutils literal notranslate\">for</code></a> loop iterates over the already filled cache.</p></li>\n</ol>\n<p>In total, this code does either one or zero database queries. The only\ndeliberate optimization performed is the use of the <a class=\"reference internal\" href=\"/ja/2.1/ref/templates/builtins/#std-templatetag-with\"><code class=\"xref std std-ttag docutils literal notranslate\">with</code></a> tag. Using\n<code class=\"docutils literal notranslate\">QuerySet.exists()</code> or <code class=\"docutils literal notranslate\">QuerySet.count()</code> at any point would cause\nadditional queries.</p>\n</section>\n<section id=\"use-queryset-update-and-delete\">\n<h3>Use <code class=\"docutils literal notranslate\">QuerySet.update()</code> and <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>Rather than retrieve a load of objects, set some values, and save them\nindividual, use a bulk SQL UPDATE statement, via <a class=\"reference internal\" href=\"/ja/2.1/topics/db/queries/#topics-db-queries-update\"><span class=\"std std-ref\">QuerySet.update()</span></a>. Similarly, do <a class=\"reference internal\" href=\"/ja/2.1/topics/db/queries/#topics-db-queries-delete\"><span class=\"std std-ref\">bulk deletes</span></a> where possible.</p>\n<p>Note, however, that these bulk update methods cannot call the <code class=\"docutils literal notranslate\">save()</code> or\n<code class=\"docutils literal notranslate\">delete()</code> methods of individual instances, which means that any custom\nbehavior you have added for these methods will not be executed, including\nanything driven from the normal database object <a class=\"reference internal\" href=\"/ja/2.1/ref/signals/\"><span class=\"doc\">signals</span></a>.</p>\n</section>\n<section id=\"use-foreign-key-values-directly\">\n<h3>Use foreign key values directly<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>If you only need a foreign key value, use the foreign key value that is already on\nthe object you've got, rather than getting the whole related object and taking\nits primary key. i.e. do:</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>instead of:</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>Don't order results if you don't care<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>Ordering is not free; each field to order by is an operation the database must\nperform. If a model has a default ordering (<a class=\"reference internal\" href=\"/ja/2.1/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>) and you don't need it, remove\nit on a <code class=\"docutils literal notranslate\">QuerySet</code> by calling\n<a class=\"reference internal\" href=\"/ja/2.1/ref/models/querysets/#django.db.models.query.QuerySet.order_by\" title=\"django.db.models.query.QuerySet.order_by\"><code class=\"xref py py-meth docutils literal notranslate\">order_by()</code></a> with no parameters.</p>\n<p>Adding an index to your database may help to improve ordering performance.</p>\n</section>\n</section>\n<section id=\"insert-in-bulk\">\n<h2>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></h2>\n<p>When creating objects, where possible, use the\n<a class=\"reference internal\" href=\"/ja/2.1/ref/models/querysets/#django.db.models.query.QuerySet.bulk_create\" title=\"django.db.models.query.QuerySet.bulk_create\"><code class=\"xref py py-meth docutils literal notranslate\">bulk_create()</code></a> method to reduce the\nnumber 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>Entry<span class=\"o\">.</span>objects<span class=\"o\">.</span>bulk_create<span class=\"p\">([</span>\n    Entry<span class=\"p\">(</span>headline<span class=\"o\">=</span><span class=\"s1\">&#39;This is a test&#39;</span><span class=\"p\">),</span>\n    Entry<span class=\"p\">(</span>headline<span class=\"o\">=</span><span class=\"s1\">&#39;This is only a test&#39;</span><span class=\"p\">),</span>\n<span class=\"p\">])</span>\n</code></pre></div>\n<p>...is preferable to:</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=\"s1\">&#39;This is a test&#39;</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=\"s1\">&#39;This is only a test&#39;</span><span class=\"p\">)</span>\n</code></pre></div>\n<p>Note that there are a number of <a class=\"reference internal\" href=\"/ja/2.1/ref/models/querysets/#django.db.models.query.QuerySet.bulk_create\" title=\"django.db.models.query.QuerySet.bulk_create\"><code class=\"xref py py-meth docutils literal notranslate\">caveats to this method</code></a>, so make sure it's appropriate\nfor your use case.</p>\n<p>This also applies to <a class=\"reference internal\" href=\"/ja/2.1/ref/models/fields/#django.db.models.ManyToManyField\" title=\"django.db.models.ManyToManyField\"><code class=\"xref py py-class docutils literal notranslate\">ManyToManyFields</code></a>, so doing:</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>...is preferable to:</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</section>","rootId":"database-access-optimization","toc":[{"title":"Profile first","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":"Use QuerySet.count()","anchor":"use-queryset-count","children":[]},{"title":"Use QuerySet.exists()","anchor":"use-queryset-exists","children":[]},{"title":"Don't overuse count() and exists()","anchor":"don-t-overuse-count-and-exists","children":[]},{"title":"Use QuerySet.update() and delete()","anchor":"use-queryset-update-and-delete","children":[]},{"title":"Use foreign key values directly","anchor":"use-foreign-key-values-directly","children":[]},{"title":"Don't order results if you don't care","anchor":"don-t-order-results-if-you-don-t-care","children":[]}]},{"title":"Insert in bulk","anchor":"insert-in-bulk","children":[]}],"breadcrumbs":[{"docname":"topics/index","title":"Django を使う","url":"/ja/2.1/topics/"},{"docname":"topics/db/index","title":"モデルとデータベース","url":"/ja/2.1/topics/db/"}],"prev":{"docname":"topics/db/tablespaces","title":"Tablespaces","url":"/ja/2.1/topics/db/tablespaces/"},"next":{"docname":"topics/db/instrumentation","title":"Database instrumentation","url":"/ja/2.1/topics/db/instrumentation/"},"formats":{"html":"/ja/2.1/topics/db/optimization/","markdown":"/ja/2.1/topics/db/optimization.md","json":"/ja/2.1/topics/db/optimization.json"},"source":"https://github.com/django/django/blob/stable/2.1.x/docs/topics/db/optimization.txt","official":"https://docs.djangoproject.com/ja/2.1/topics/db/optimization/","inVersions":["6.1","6.0","5.2","5.1","5.0","4.2","4.1","4.0","3.2","3.1","3.0","2.2","2.1","2.0","1.11","1.10","1.9"],"inLocales":["en","zh-hans","fr","ja","id","pt-br","ko","es","el","pl"]}