Question

Je travaille sur un site Web avec une base de données normalisée simple.

Il existe une table appelée Pages et une table appelée Vues. Chaque fois qu'une page est affichée, un enregistrement unique de cette vue est enregistré dans le tableau Vues.

Lors de l'affichage d'une page sur le site, j'utilise un simple compte MySQL () pour totaliser le nombre de vues à afficher.

La conception de la base de données semble correcte, à l'exception de ce problème: je ne sais pas comment récupérer les 10 pages les plus consultées parmi des milliers.

Dois-je dénormaliser le tableau Pages en ajoutant une colonne Pages.views afin de contenir le nombre total de vues pour chaque page? Ou existe-t-il un moyen efficace d’interroger les 10 pages les plus consultées?

Était-ce utile?

La solution

   SELECT p.pageid, count(*) as viewcount FROM 
   pages p
   inner join views v on p.pageid = v.pageid
   group by p.pageid
   order by count(*) desc   
   LIMIT 10 OFFSET 0;

Je ne peux pas tester cela, mais quelque chose dans ce sens. Je ne voudrais pas stocker la valeur sauf si cela est nécessaire en raison de contraintes de performances (je viens d'apprendre le terme "optimisation prématurée" et il semble s'appliquer si vous le faites).

Autres conseils

Cela dépend du niveau d’information que vous essayez de conserver. Si vous voulez enregistrer qui a vu quand? Ensuite, la table séparée est bien. Sinon, une colonne pour Vues est la voie à suivre. De même, si vous conservez une colonne distincte, vous constaterez que la table sera verrouillée plus souvent, chaque vue de page tentant de mettre à jour la colonne pour la ligne correspondante.

Select pageid, Count(*) as countCol from Views
group by pageid order by countCol DESC
LIMIT 10 OFFSET 0;

J'inclurais probablement la colonne des vues dans le tableau Pages.

Cela me semble être une rupture parfaitement raisonnable de la normalisation. Surtout que je ne peux pas vous imaginer en train de supprimer des vues, de sorte que vous ne vous attendez pas à ce que le décompte se détraque. L'intégrité référentielle ne semble pas super critique dans ce cas.

La normalisation de la base de données concerne le moyen le plus efficace / le moins redondant de stocker des données. C'est bon pour le traitement des transactions, mais souvent en conflit direct avec le besoin d'extraire efficacement les données. Le problème est généralement résolu en disposant des tables dérivées (index, vues matérialisées, tables de synthèse, etc.) avec des données plus accessibles et prétraitées. Le mot à la mode (légèrement daté) est Data Warehousing.

Je pense que vous souhaitez conserver votre table Pages normalisée, mais disposer d'une table supplémentaire avec les totaux. Selon la date à laquelle ces comptes doivent être récents, vous pouvez mettre à jour le tableau lorsque vous mettez à jour le tableau d'origine ou disposer d'un travail en arrière-plan pour recalculer périodiquement les totaux.

Vous souhaitez également le faire uniquement si vous rencontrez un problème de performances, ce que vous ne ferez pas sauf si vous avez un très grand nombre d'enregistrements ou un très grand nombre d'accès simultanés. Gardez votre code flexible pour pouvoir basculer entre avoir la table et ne pas en avoir.

Dénormaliser serait certainement fonctionner dans ce cas. Votre perte est la salle de stockage supplémentaire utilisée par la colonne supplémentaire.

Vous pouvez également configurer un travail planifié pour renseigner ces informations tous les soirs, chaque fois que votre trafic est faible, x fois.

Dans ce cas, vous perdriez la possibilité de connaître instantanément le nombre de pages que vous utilisiez, sauf si vous exécutez cette requête manuellement.

La dénormalisation peut certainement être utilisée pour améliorer les performances.

- Kris

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top