DB /パフォーマンス:親を複数回参照することはめったにないdjangoモデルのレイアウト
-
10-07-2019 - |
質問
架空の単純化された都市を提示するアプリがあります。
次のDjangoモデルを検討してください:
class City(models.Model):
name = models.CharField(...)
...
TYPEGROUP_CHOICES = (
(1, 'basic'),
(2, 'extra'),
)
class BldgType(models.Model):
name = models.CharField(...)
group = models.IntegerField(choices=TYPEGROUP_CHOICES)
class Building(models.Model):
created_at = models.DateTimeField(...)
city = models.ForeignKey(City)
type = models.ForeignKey(BldgType)
other_criterion = models.ForeignKey(...)
class Meta:
get_latest_by = 'created_at'
この設定を選択するための説明:
(1)各都市には、「基本」の特定の建物があります。都市ごとに1回だけ発生するタイプ(例:市役所、消防署、警察署、病院、学校)および「余分な」建物の数十の建物ダンスクラブなどのタイプ。
(2)特定のビューでは、すべての建物(都市などに関係なく)は、たとえば other_criterion
などのさまざまな基準に従ってフィルタリングされます。
問題/懸念:
city_detail
ビューでは、「追加」の建物をループする必要があります。タイプ、これはOKで通常です。
しかし、市の「病院」を効率的に取得する方法がわかりません。 「基本」の建物と入力します。このような病院は各都市に1つだけ存在するため、とにかくすべての都市でこれを行う必要があります(これは都市の作成時に保証されます)。
「基本」は最大で12個あります。建物の種類。そのうち約半分が常に表示されます。
Cityモデルで便利なメソッドを作成する傾向があり、次の3つのオプションに直面しています。
(A1) try
およびインデックス経由: .filter(...)[0]
(A2) try
および .get(...)
(A3) try
および .filter(...)。latest()
しかし、それらはどれもエレガントに見えません。
または、これら3つのオプションの1つは、 User
モデルのDjangoの get_profile()
メソッドのように、何らかのキャッシュと組み合わせるのに適していますか?残念ながら、私はまだキャッシュの経験がありません。
次のオプションを使用するのは簡単ですか?
(B)Cityモデルの特定のFK、最も重要な基本タイプごとに1つ
質問:
どのオプションが最も意味がありますか?
または、この種のシナリオではスキーマに一般的な欠陥がありますか?
特にDBのパフォーマンスに関して、何を提案しますか?まったく異なるアプローチが必要ですか?
アドバイスしてください! :)
事前に感謝します!
解決
市が市役所、消防署、警察署、病院、学校などをそれぞれ1つしか持てない場合、これを実施する最も簡単な方法は、それぞれをモデルのフィールドとして宣言することです。
class City(models.Model):
name = models.CharField(...)
city_hall = models.ForeignKey(Building)
fire_station = models.ForeignKey(Building)
# ... et cetera
これも「乱雑」だと思ったらCityモデルでは、中間の CityBuildings
モデルの使用を検討できます。
class CityBuildings(models.Model):
city_hall = models.ForeignKey(Building)
fire_station = models.ForeignKey(Building)
# ... et cetera
class City(models.Model):
name = models.CharField(...)
buildings = models.OneToOneField(CityBuildings)
次に、たとえば city.buildings.fire_station
これらは単なる提案です...どちらの方法がより「正しい」のかはわかりません
他のヒント
興味のある人には:愚かな私はメモ化手法の存在を発見したので、(A2)に適用されるもののいくつかの形式を使用します。建物タイプ。
これは、少なくとも2方向のFKを使用するよりも面倒ではなく、関心の分離(一方の側でのモデリング、もう一方の側でのパフォーマンス)についてコードをより明確にします。
すぐに、学習と、場合によっては貸し出しまたは直接申請を検討するために、2つのプロジェクトを作成しました。
- django-memoize
- github.com/husio/django-easycache /
誰かがこれも役に立つと思うかもしれません。