Django非规范化和一致性:

Tot*_*.js 1 django consistency denormalization

因为我在Django中很新,所以我在这里要求对Django中进行非规范化的最佳实践提出一些建议.按照我的意见,我正在考虑做这样的事情:

我有2个型号:

类别:

 name = m.CharField(max_length = 127)
Run Code Online (Sandbox Code Playgroud)

文章:

 name = m.CharField(max_length = 127)
 category = m.ForeignKey(Category)
 category_name = m.CharField(max_length = 127)
Run Code Online (Sandbox Code Playgroud)

我希望这发生:

当我更改任何类别的名称以反映所有文章中的更改时.现在,当我们没有一个或两个字段但大约10-20个字段保持同步时,最佳做法是什么?

谢谢你的帮助 (:

Mar*_*mro 5

建议在遇到性能问题时才使用关系和非规范化,并且只有在确认此错误性能与查询类别名称相关时才会使用.否则它只是在没有充分理由的情况下增加复杂性.请记住Donald Knuth的名言:

过早优化是万恶之源.

关系数据库擅长连接,因为基本上就是它们的设计目的.在你想要的非规范化设计中,JOINs你需要复杂而不是最简单的设计UPDATEs.这些更新将影响许多(10-20)表中的许多行.如果受影响的表中有大量数据并且经常更改category_name,它甚至会使性能变差.


如果您真的坚持category_name在10-20个表中考虑使用数据库触发器.更改类别表时将执行触发器.它可以在数据库内部处理所有更新.无需更改Django项目中的任何内容,并且开销较小.

因此,如果您真的坚持使用category_name10-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)
Run Code Online (Sandbox Code Playgroud)