DB /パフォーマンス:親を複数回参照することはめったにないdjangoモデルのレイアウト

StackOverflow https://stackoverflow.com/questions/1821778

質問

架空の単純化された都市を提示するアプリがあります。

次の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つのプロジェクトを作成しました。

  1. django-memoize
  2. github.com/husio/django-easycache /

誰かがこれも役に立つと思うかもしれません。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top