Дженго денормализация и последовательность: - PullRequest
1 голос
/ 04 ноября 2011

Поскольку я совсем новичок в Джанго, я прошу здесь дать небольшое предложение о лучших методах проведения денормализации в Джанго. Что касается меня, я думаю сделать что-то вроде этого:

У меня есть 2 модели:

Категория:

 name = m.CharField(max_length = 127)

Статьи:

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

Я бы хотел, чтобы это произошло:

Когда я изменяю название любой категории, чтобы отразить изменения во всех статьях. Теперь, что действительно является лучшей практикой, когда у нас есть не одно или 2 поля, а около 10-20 для синхронизации?

спасибо за вашу помощь (:

1 Ответ

5 голосов
/ 24 февраля 2012

I рекомендую с использованием отношений и денормализации только , если у вас есть проблемы с производительностью и только после того, как вы подтвердили, что эта плохая производительность связана с запросом имени категории.В противном случае это просто сложность без веской причины.Имейте в виду знаменитая цитата Дональда Кнута:

Преждевременная оптимизация - корень всего зла.

Реляционные базы данных хороши при объединениях, потому что в основномэто то, для чего они были созданы.В денормализованном дизайне, который вы хотите, вместо самого простого JOINs вам понадобится комплекс UPDATEs.Эти обновления будут влиять на множество строк во многих (10-20) таблицах.Если у вас есть много данных в затронутых таблицах и вы часто меняете имя_категории, это может / даже ухудшит производительность.


Если вы действительно застряли с идеей category_name в 10-20 таблицах, рассмотрите возможность использования триггера базы данных .Триггер будет выполнен при изменении таблицы категорий.Он может обрабатывать все обновления внутри базы данных.Не изменяя ничего в вашем проекте Django и с меньшими накладными расходами.

Так что, если вы действительно застряли с идеей category_name в 10-20 таблицах и вы не можете использовать триггерыв Django есть механизм, называемый сигналов .Это триггеры, встроенные в 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)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...