Je recommandons en utilisant les relations et dénormaliser que si vous avez des problèmes de performance et seulement après avoir confirmé que cette mauvaise performance est liée à l'interrogation du nom de la catégorie Dans le cas contraire. il est juste d'ajouter la complexité sans une bonne raison Gardez à l'esprit Donald Knuth's célèbre citation:..
l'optimisation prématurée est la racine de tous les maux
Les bases de données relationnelles sont bonnes dans les jointures, car c'est ce à quoi elles ont été conçues. Dans le design dénormalisé que vous voulez, au lieu de la plus simple possible, vous aurez besoin UPDATEs
complexe. Ces mises à jour affecteront de nombreuses lignes dans de nombreuses tables (10-20). Si vous avez beaucoup de données dans les tables affectées et que vous modifiez souvent le nom de la catégorie, cela pourrait même aggraver les performances.
Si vous êtes vraiment coincé avec l'idée de category_name
à 10-20 tables envisager d'utiliser un database trigger. Le déclencheur sera exécuté quand une table de catégorie est changée. Il peut gérer toutes les mises à jour en interne dans la base de données. Sans rien changer dans votre projet Django et avec moins de frais généraux.
Donc, si vous êtes vraiment coincé avec l'idée de category_name
dans 10-20 tables et vous ne pouvez pas utiliser des déclencheurs, il y a un mécanisme appelé signals dans Django. Ce sont des sortes de déclencheurs intégrés dans Django et déclenchés avant/après un événement défini.
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)
Cela semble être un cas étrange de dénormalisation. Pourquoi pensez-vous que vous en avez besoin? Êtes-vous sûr d'avoir un goulot d'étranglement pour obtenir les informations sur la catégorie? –
Si je devais montrer une liste d'articles avec leur marque, je devrais faire une jointure interne. Dans ce cas je n'aurais besoin d'aucune jointure ... –
C'est évidemment vrai, mais qu'est-ce qui ne va pas avec une jointure? Les bases de données sont bonnes dans ces domaines. La dénormalisation est seulement nécessaire si vous avez déterminé que vous avez définitivement un problème de performance à ce moment-là. –