Question

J'écris ce qui sera une application intranet, et l'une de ses fonctionnalités est à peu près analogue au vote de contenu - un peu comme ce que font SO, Amazon et de nombreux autres sites.

En supposant que chaque élément de contenu faisant l'objet d'un vote ait un identifiant unique et que chaque utilisateur (qu'ils soient authentifiés) ait un identifiant unique, le moyen le plus simple semble être d'avoir un " votes " table ...

ContentID int
UserID int
VoteValue int

Mais cela crée une ligne par vote - avec des millions d'éléments de contenu et des dizaines de milliers d'utilisateurs, ce tableau sera énorme. Est-ce la meilleure façon de le faire? Je veux dire, si un int prend 4 octets, chaque ligne prend 12 octets. Si un million d'éléments de contenu obtiennent une centaine de voix, c'est plus de 400 Mo de stockage, oui? Semble ... beaucoup :). Même si VoteValue est un très petit (ce qui est probablement bien) et qu’un octet, il reste quelques centaines de mégaoctets dans le tableau. Je veux dire sheesh.

Existe-t-il un moyen plus intelligent? Dois-je stocker ces "votes"? table dans une base de données séparée (en ignorant les problèmes potentiels d’intégrité des données) afin de la partitionner à partir du fichier "principal". données en termes de stockage et de performances?

(Je me rends bien compte que dans le monde d'aujourd'hui, 400 Mo ne représentent pas une tonne, mais cela ressemble beaucoup à stocker des votes, oui?)

Était-ce utile?

La solution

Personnellement, tant que vous avez de bons index en place, vous vous y prenez correctement. En fonction de votre utilisation, vous voudrez peut-être éviter de toucher à la table des votes en stockant des informations de décompte secondaires. Toutefois, dans l’ensemble, si vous devez suivre le vote de l’OMS, vous devez le faire de la manière indiquée.

Cela ne me dérangerait pas de passer à une autre base de données. Si vous êtes VRAIMENT concerné par SQL Server, vous pouvez créer un groupe de fichiers distinct pour le contenir ..... mais probablement pas nécessaire.

Autres conseils

Bien, oui, mais vous devez regarder la situation dans son ensemble. Avec un million de contenus:

(taille du contenu) > > (Taille des votes): où " > > " signifie "beaucoup plus grande".

Si vous avez un million d'éléments de contenu, il peut s'agir d'un téraoctet de données pour lequel le nombre de votes est de 400 Mo. La bonne affaire, non?

J'ajouterais également que si vous êtes préoccupé par l'évolutivité, consultez ce blog:

http://highscalability.com/

Si vous devez savoir si un utilisateur a voté pour un élément en particulier et s'il existe différentes valeurs de vote (par exemple, 1 étoile sur 5 étoiles), il s'agit d'un format aussi compact que possible.

N'oubliez pas que pour des vitesses d'accès raisonnables, vous devez indexer les données (deux index, probablement - l'un avec ContentID comme colonne de tête, l'autre avec userID comme colonne de tête).

Vous devrez déterminer s’il existe une raison de ne pas stocker la table séparément des autres tables. Cela dépend du SGBD utilisé: avec Informix, la table se trouverait dans la même base de données mais serait stockée dans un dbspace différent, et les index pourraient éventuellement être stockés dans deux autres espaces de base différents.

Vous voudrez probablement également connaître l’identité de l’auteur du contenu du tableau afin de détecter plus facilement les abus de vote. (Oui, il s'agit probablement d'informations redondantes. Une autre solution consiste à créer régulièrement un tableau récapitulatif pour savoir qui vote sur qui.)

Pour ce que cela vaut, le tableau de vote perlmonks se présente comme suit:

 `vote_id` int(11) NOT NULL default '0',
 `voter_user` int(11) NOT NULL default '0',
 `voted_user` int(11) default NULL,
 `weight` int(11) NOT NULL default '0',
 `votetime` datetime NOT NULL default '0000-00-00 00:00:00',
 `ip` varchar(16) default NULL,
 PRIMARY KEY  (`vote_id`,`voter_user`),
 KEY `voter_user_idx` (`voter_user`,`votetime`),
 KEY `voted_user_idx` (`voted_user`,`votetime`)

(vote_id est l'ID du contenu, ip est une adresse IP.)

Je dirais que vous devez déterminer comment ces votes seront utilisés et concevoir des requêtes spécifiques pour votre modèle de données. Ce n'est pas nécessairement un modèle SQL. Si vous venez du monde SQL, consulter le didacticiel officiel de MongoDB aide à clarifier les idées au début.

Par exemple, si vous n’avez besoin que de stocker et d’afficher les votes pour une page à numéro unique, il peut être pratique de stocker les votes dans un seul champ de chaîne du numéro, qui ressemblera à id1: id2: id3: . En supposant que tous les identifiants aient la même longueur, il existe quelques propriétés intéressantes:

  1. Comptez tous les votes pour le problème:

    len (issue.votes) / len (id)

  2. Trouver j'ai voté sur la question

    myid dans issue.votes

  3. Trouvez toutes les questions sur lesquelles vous avez voté:

    sélectionnez issue.id dans les numéros où issue.votes contient (myid)

  4. Trouvez les problèmes les plus votés

    sélectionnez issue.id dans l'ordre des questions, ordre par len (issue.votes) desc limite 10

Cette architecture permet d'éviter des calculs coûteux en lecture dans ces cas spécifiques, mais la mise à jour de issue.votes lors du vote pourrait être plus coûteuse que l'ajout d'une ligne dans une table. Dans ce cas, 100 votes avec 4 octets par id + séparateur est une chaîne de 500 octets. Dans votre variante proposée, 100 voix sont 800 octets.

Clause de non-responsabilité: je n'ai jamais implémenté une telle fonctionnalité, ce n'est qu'une idée.

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