Mon choix serait une variante de l'approche 2. Le gras indique les champs de la clé primaire.
- Vous insérez chaque article dans un tableau
articles_versioned
(identifiant , horodatage , nom, texte) - Votre deuxième table est
articles
(identifiant , horodatage, [nom, texte]). Notez que l'horodatage n'est pas principal ; le nom et le texte peuvent être répliqués, ou vous pouvez utiliser une jointure avecarticles_versioned
(ce qui sera rapide puisque l'id et l'horodatage sont lesarticles_versioned
clé primaire) articles_versioned
a un déclencheur sur l'insertion qui prend la ligne qui vient d'être insérée et la réplique surarticles
- Pour restaurer une version spécifique d'un article, vous modifiez les
articles
tableau.
Les avantages de cette approche sont :
- Vous obtenez gratuitement une autre information (la date et l'heure de l'article) dans votre tableau, dont vous pourriez avoir besoin de toute façon
- Vous n'avez pas besoin d'interroger la base de données pour obtenir la date actuelle. Si vous utilisez la version, vous devez.
- Votre code n'a pas besoin d'insérer l'article dans deux tables. Vous insérez simplement dans
articles_versioned
et lire desarticles
, la base de données se charge de migrer les données au fur et à mesure que vous les insérez via le déclencheur, évitant ainsi tout problème de cohérence.
Les inconvénients
- Dans un environnement fortement concurrent, deux versions peuvent être insérées en même temps, de sorte que l'une d'entre elles peut échouer. Cela ne devrait pas être un problème lors de l'insertion d'articles écrits par l'utilisateur (c'est très peu probable compte tenu de la précision des horodatages de nos jours). Si vous ne spécifiez pas l'horodatage dans votre
INSERT
, mais à la place vous définissez le champ datetime pour avoir l'heure actuelle comme valeur par défaut, vous pouvez éviter ce problème entièrement.
Pour répondre au reste de ta question. L'approche 1 ne conduira pas à des requêtes plus longues tant que vous ajoutez un index sur le statut. Cela n'a de sens que si vous avez tendance à avoir de nombreuses versions différentes de chaque article; tant que vous avez 2 versions par article en moyenne ou moins, l'index ne fera que vous ralentir, et l'approche 2 ne serait de toute façon pas sensiblement plus rapide (même si je recommanderais toujours mon approche car elle simplifie le code, car la restauration d'une version le fait ne nécessite pas de changement de statut pour deux lignes).
Les ressources associées, telles que les images, doivent suivre une version similaire. Je suppose que vous les enregistrez sur le système de fichiers ; au lieu de les enregistrer avec leur vrai nom, utilisez une table (id , image_name) pour donner à chaque image un identifiant, puis enregistrez l'image sous -id-.jpg
. Le champ image_name vous permettra de connaître le nom du fichier d'origine (si cela vous intéresse). De cette façon, vous pouvez versionner les images de la même manière que vous versionnez les articles, et dans les articles, vous utiliserez quelque chose comme <img src="-id-.jpg">
, dont vous savez qu'ils resteront disponibles pour toujours.