2013-05-30 2 views
1

가정하자 나는 두 개의 관련된 푸의 인스턴스가 자주 바의 여러 인스턴스를 가질 것 모델 장고 - 관련 모델 필드를 사용하여 성능

class Foo(models.Model): 
    value = models.FloatField() 

class Bar(models.Model): 
    multiplier = models.FloatField() 
    foo = models.ForeignKey(Foo, related_name="bars") 

    def multiply(self): 
     return self.foo.value * self.multiplier 

하지만, 바 저장 않는 계산에 관련된 몇 가지 정보를

foo = Foo.objects.latest() 
[x.multiply() for x in foo.bars.all()] 

그것은 타격 끝 : (가 관련 바의 모든 인스턴스에 대해 동일하기 때문에) 푸에

문제는 내가 같은 것을 할 때입니다 데이터베이스는 foo.bars.all()의 모든 Bar 객체가 Foo 객체에 대해 데이터베이스를 쿼리하기 때문에 많이 사용됩니다. 따라서 10 개의 막대가있는 경우 11 개의 데이터베이스 쿼리 (10 개의 막대가있는 쿼리 세트를 얻으려면 1, self.foo.value를 얻으려면 다시 도달하는 각 막대 개체에 1)가 발생합니다. select_related()를 사용하면 도움이되지 않습니다.

내 질문 : 1) memcached (예 : Johnny Cache, Cache Machine)가이 문제를 해결할 것이라고 생각합니까? 2) 캐시없이 명령을보다 효율적으로 만들 수있는 개체 관계를 디자인하는 방법이 있습니까?

+0

왜 11 개의 쿼리입니까? 그것은 단지 2 개의 쿼리 일 것입니다. – karthikr

+0

죄송합니다. 오타 였으므로 foo.bars.all()에서 [x.multiply()] 여야합니다. multiply()에는 foo에 저장된 값이 필요하므로 multiply()를 호출 할 때마다 foo를 검색해야합니다. – hgcrpd

답변

3

정확히 select_relatedprefetch_related이 생성 된 상황입니다. Django의 ORM은 JOIN (select_related)을 통한 관계를 따르거나 QuerySets에서 일대 다/다 대다 관계를 사전 캐싱하는 두 가지 기술 중 하나를 사용하여 중복 데이터베이스 요청을 방지합니다.

# Hits the database 
foo = Foo.objects.prefetch_related('bars').latest() 

# Doesn't hit the database 
[x.value for x in foo.bars.all()] 
+0

prefetch_related()였습니다. 감사! – hgcrpd