1. ホーム
  2. データベース
  3. その他のデータベース

Djangoプロジェクト最適化データベース運用まとめ

2022-01-17 11:05:27

参考URL:Django公式データベース最適化

QuerySet.explain() を使用して、 データベースが特定の QuerySet をどのように実行するかを調べます。

また、django-debug-toolbar のような外部プロジェクトや、データベースを直接監視するツールを使用するのもよいでしょう。

賢明にインデックスを作成する

インデックスはクエリの高速化に役立ちますが、インデックスにはディスクスペースが必要であり、不要なインデックスを作成すると無駄が増えるだけであることに注意してください。 <マーク
では、どのフィールドにインデックスを付ける必要があるのでしょうか?これは良い意味で不可解な質問ですが、以下のリストが参考になります。

  • WHERE条件句に頻繁に登場するフィールド(Djangoではfilterでフィルタリングされるフィールドと呼ばれる)。
  • グループ分けや並べ替えによく使われるフィールド
  • アクセス頻度の高い複数の列に対して複合インデックスを作成するが、複合インデックスの順番は使用頻度によって決まるので注意すること
class ModelName(models.Model):
	# Field is indexed using db_index
	name = models.CharField(db_index=True, max_length=100)
	class Meta:
		# Joint unique indexes using index_together
		index_together = ('field1', 'field2')


永続的なデータベース接続を設定する

SQL実行回数の削減

データベースに何度もアクセスすることは、1回のアクセスですべてを問い合わせるよりも効率が悪くなります。そのため <マーク

select_related()。SQL 接続を作成し、関連オブジェクトのフィールドを SELECT 文に含めます。 <マーク

# Standard queries
# Hits the database.
e = Entry.objects.get(id=5)
# Hits the database again to get the related Blog object.
b = e.blog
# select_related query
# Hits the database.
e = Entry.objects.select_related('blog').get(id=5)
# Doesn't hit the database, because e.blog has been prepopulated
# in the previous query.
b = e.blog


prefetch_related(): <マーク

from django.db import models
class Topping(models.Model):
    name = models.CharField(max_length=30)
class Pizza(models.Model):
    name = models.CharField(max_length=50)
    toppings = models.ManyToManyField(Topping)
    def __str__(self):
        return "%s (%s)" % (
            self.name,
            ", ".join(topping.name for topping in self.toppings.all()),
        )
# good
pizza.objects.all().prefetch_related('toppings')




必須フィールドのデータのみを取得する

QuerySet.values()とvalues_list()を使用します。

QuerySet.defer()とonly()を使用します。

QuerySet.count()を使用します。

QuerySet.exists()を使用します。

count()とexists()は使い過ぎないようにしましょう。

結果をランダムにソートすることなく、一括作成、更新、削除を使用します。

一括作成。オブジェクトを作成する際には、可能な限り bulk_create() メソッドを使用し、SQL クエリの回数を減らすようにしましょう。例えば

# Good
Entry.objects.bulk_create([
    Entry(headline='This is a test'),
    Entry(headline='This is only a test'),
])
# Bad
Entry.objects.create(headline='This is a test')
Entry.objects.create(headline='This is only a test')


<マーク

# Good
entries[0].headline = 'This is not a test'
entries[1].headline = 'This is no longer a test'
Entry.objects.bulk_update(entries, ['headline'])
# Bad
entries[0].headline = 'This is not a test'
entries[0].save()
entries[1].headline = 'This is no longer a test'
entries[1].save()


<マーク
一括挿入。複数のオブジェクトで add() を使用すると、ManyToManyFields にオブジェクトを挿入する際の SQL クエリーの数を減らすことができます。

# good
my_band.members.add(me, my_friend)
# Bad
my_band.members.add(me)
my_band.members.add(my_friend)
# Good
PizzaToppingRelationship = Pizza.toppings.through
PizzaToppingRelationship.objects.bulk_create([
    PizzaToppingRelationship(pizza=my_pizza, topping=pepperoni),
    PizzaToppingRelationship(pizza=your_pizza, topping=pepperoni),
    PizzaToppingRelationship(pizza=your_pizza, topping=mushroom),
], ignore_conflicts=True)
# Bad
my_pizza.toppings.add(pepperoni)
your_pizza.toppings.add(pepperoni, mushroom)


<マーク
一括削除 ManyToManyFields からオブジェクトを削除する場合、複数のオブジェクトで remove() を使用すると、SQL クエリの数を減らすことができます。

例えば

# Good
my_band.members.remove(me, my_friend)
# Bad
my_band.members.remove(me)
my_band.members.remove(my_friend)
# Good
from django.db.models import Q
PizzaToppingRelationship = Pizza.toppings.through
PizzaToppingRelationship.objects.filter(
    Q(pizza=my_pizza, topping=pepperoni) |
    Q(pizza=your_pizza, topping=pepperoni) |
    Q(pizza=your_pizza, topping=mushroom)
).delete()
# Bad
my_pizza.toppings.remove(pepperoni)
your_pizza.toppings.remove(pepperoni, mushroom)


上記は、データベースの操作の詳細を最適化するためのDjangoプロジェクトの概要であり、データベースを最適化するためのDjangoプロジェクトの詳細については、スクリプトホーム他の関連記事に注意を払うください