Django ORM のクエリ最適化と SQL チューニングを解説。select_related, prefetch_related, N+1 問題の回避方法を紹介。
Django の ORM は便利ですが、適切に使わないと大量のクエリが発生し、パフォーマンスが低下することがあります。
本記事では、ORM を使いながら SQL を最適化する方法を紹介します。
select_related
と prefetch_related
で N+1 問題を回避Django では、リレーションを持つデータを取得するときに N+1 問題
が発生することがあります。
PYTHONusers = User.objects.all() for user in users: print(user.profile.bio) # Profile を取得するたびに SQL クエリが発行される
上記コードでは、User
を取得した後、Profile
にアクセスするたびに個別の SQL クエリが発生します。
select_related
(JOIN を使う)PYTHONusers = User.objects.select_related("profile").all()
select_related
は JOIN
を使って関連データを一度に取得するため、クエリ回数が削減されます。
prefetch_related
(別クエリで取得してキャッシュ)PYTHONusers = User.objects.prefetch_related("profile").all()
prefetch_related
は複数のクエリを発行しますが、事前にキャッシュして関連データをまとめて取得できます。
only()
と defer()
で不要なデータを取得しないonly()
を使うと、取得するフィールドを限定できます。
PYTHONusers = User.objects.only("id", "name")
逆に defer()
を使うと、不要なフィールドを除外できます。
PYTHONusers = User.objects.defer("bio")
Django の QuerySet
には .explain()
メソッドがあり、実行計画を確認できます。
PYTHONqueryset = User.objects.filter(name="Taro") print(queryset.explain())
PostgreSQL の場合、ANALYZE
を使うと詳細な情報を確認できます。
PYTHONqueryset = User.objects.filter(name="Taro") print(queryset.explain(analyze=True))
EXPLAIN
を使った SQL の分析Django ORM で発行される SQL のパフォーマンスを分析するには EXPLAIN
を使います。
SQLEXPLAIN ANALYZE SELECT * FROM users WHERE name = 'Taro';
頻繁に検索するカラムには db_index=True
を設定することで検索を高速化できます。
PYTHONclass User(models.Model): name = models.CharField(max_length=100, db_index=True)
また、複数のカラムに対する検索を最適化するには、Meta.indexes
を活用できます。
PYTHONfrom django.db.models import Index class User(models.Model): name = models.CharField(max_length=100) email = models.EmailField(unique=True) class Meta: indexes = [ Index(fields=["name", "email"]), ]
最適化手法 | SQLite | PostgreSQL |
---|---|---|
select_related / prefetch_related | あり | あり |
EXPLAIN ANALYZE | 制限あり | あり(詳細な情報を取得可能) |
INDEX のサポート | あり | あり(GIN, GiST など高機能インデックスあり) |
クエリの並列処理 | なし | あり(並列クエリの最適化が可能) |
select_related
は JOIN
を使って関連データを最適化prefetch_related
は別クエリをキャッシュして関連データを取得only()
や defer()
で不要なデータの取得を減らすEXPLAIN
や ANALYZE
を使ってクエリの実行計画を確認回 | タイトル | リンク |
---|---|---|
第 1 回 | Django ORM と SQL の関係 | 詳 細 |
第 2 回 | モデル定義とマイグレーション | 詳 細 |
第 3 回 | ORM のクエリ最適化と SQL チューニング | この記事 |
第 4 回 | JOIN と GROUP BY を活用したデータ分析 | 詳 細 |
第 5 回 | INDEX の活用とパフォーマンス最適化 | 詳 細 |
第 6 回 | TRANSACTION を使ったデータ整合性の管理 | 詳 細 |
第 7 回 | VIEW を使った仮想テーブルの活用 | 詳 細 |
当サイトの情報は、一般的な参考情報として提供しております。
正確な情報の掲載に努めておりますが、その内容の正確性・完全性・最新性を保証するものではありません。
記事の内容をご利用の際は、ご自身の責任において判断し、必要に応じて専門家にご相談ください。
当サイトの情報の利用により生じたいかなる損害についても、一切の責任を負いかねますのでご了承ください。
※ 本ページでは、著作権法に基づき、適正な引用の範囲内でコンテンツを紹介しています。
オリジナルの情報は発信元をご確認ください。
もし問題がありましたら、こちら からお問い合わせください。