2011-11-04 2 views
1

장고에서 꽤 새로운 점은 장고에서 비정규 화를 수행하는 모범 사례에 대한 약간의 제안을 요청하는 것입니다. 나 당 나는이 같은 일을 생각하고 같이Django 비정규 화 및 일관성 :

카테고리 :

name = m.CharField(max_length = 127) 

기사 :이 일이하고 싶은

name = m.CharField(max_length = 127) 
category = m.ForeignKey(Category) 
category_name = m.CharField(max_length = 127) 

을 나는이 개 모델을 가지고 :

모든 기사의 변경 사항을 반영하여 카테고리의 이름을 변경할 때. 이제는 하나 또는 두 개의 필드가 없지만 동기화를 유지하기 위해 약 10-20 개의 필드가없는 경우 실제로 가장 좋은 방법은 무엇입니까? 당신의 도움에 대한

감사 (:

+0

이것은 비정규 성화의 경우처럼 보입니다. 왜 필요하다고 생각하니? 카테고리 정보를 가져 오는 데 병목이 있습니까? –

+0

브랜드 목록에 제품 목록을 표시해야한다면 Inner Join을해야합니다. 이 경우에는 어떤 join도 필요하지 않을 것입니다 ... –

+2

분명히 사실이지만, join에 무엇이 잘못 되었습니까? 데이터베이스는 그것들에 능숙합니다. 비정규 화는 그 시점에서 성능 문제가 확실히 있다고 판단한 경우에만 필요합니다. –

답변

5

내가이 관계를 사용하고이 나쁜 성능 범주 이름을 쿼리 관련이 있음을 확인 후 성능 문제가있는 경우와 에만를 비정규 추천 그렇지. 그냥 좋은 이유없이 복잡성을 추가의 마음 Donald Knuth's 유명한 인용하십시오 :..

조기 최적화는 모든 악의 뿌리입니다

기본적으로 관계형 데이터베이스는 조인에 적합하기 때문에 기본적으로 설계되었습니다. 원하는 비정규 화 된 디자인에서 가장 간단한 가능한 JOINs 대신에 UPDATEs이 필요합니다. 이 업데이트는 많은 (10-20) 테이블의 많은 행에 영향을 미칩니다. 영향을받은 테이블에 많은 데이터가 있고 category_name을 자주 변경하면 성능이 악화 될 수 있습니다.


database trigger를 사용하는 것을 고려하면 정말 category_name 10 ~ 20에있는 테이블의 아이디어와 함께 붙어있는 경우. 카테고리 테이블이 변경되면 트리거가 실행됩니다. 데이터베이스의 내부적으로 모든 업데이트를 처리 할 수 ​​있습니다. Django 프로젝트에서 아무것도 변경하지 않고 오버 헤드를 줄입니다.

당신이 정말로 10 ~ 20 개 테이블에 category_name의 아이디어에 붙어있어 당신이 수 없습니다 사용 장고에 signals라는 메커니즘이의 트리거 그래서 경우. 이것들은 Django에 내장 된 트리거의 일종으로, 정의 된 이벤트 전후에 실행됩니다.

from django.db.models import signals 
from django.core.exceptions import DatabaseError 

class Category(m.Model): 

    def __init__(self, *args, **kwargs): 
     super(Category, self).__init__(*args, **kwargs) 

     # Store the initial name 
     self._name = self.name 

    name = m.CharField(max_length = 127) 

def update_category_name(sender, instance, **kwargs): 
    """ Callback executed when Category is about to be saved """ 

    old_category = instance._name 
    new_category = instance.name 

    if old_category != new_category:  # Name changed 

     # Start a transaction ? 

     try: 
      # Update the data: 

      # Make category_name an db_index, otherwise it will be slooooooooow 
      Article.objects.filter(category_name=old_category).update(category_name=new_category) 

      # commit transaction ? 

     except DatabaseError as e: 
      # rollback transaction ? 
      # prevent saving the category as database will be inconsistent 

      raise e 

# Bind the callback to pre_save singal 
signals.pre_save.connect(update_category_name, sender=Category) 
관련 문제