2008-12-05 16 views
13

Escribo lo que será una aplicación de intranet, y una de sus características es más o menos análoga a la votación de contenido, como lo hacen SO, Amazon y muchos otros sitios.Almacenamiento de "votos" en una base de datos

Suponiendo que cada pieza de contenido VOTable tiene un identificador único, y cada usuario (que están autenticados) tiene un identificador único, la forma más fácil parecería ser la de tener una mesa de "útiles" ...

ContentID int 
UserID int 
VoteValue int 

Pero esto crea una fila por voto: con millones de contenido y decenas de miles de usuarios, esa mesa será enorme. ¿Es esta la mejor manera de hacerlo? Quiero decir, si un int toma 4 bytes, cada fila toma 12 bytes. Si un millón de contenido obtiene cien votos, eso equivale a 400 MB más en almacenamiento, ¿no? Parece ... me gusta mucho :). Incluso si VoteValue es una minúscula (que probablemente esté bien) y solo 1 byte, todavía hay un par de cientos de megabytes en la tabla. Quiero decir Sheesh.

¿Hay alguna manera más inteligente? ¿Debería guardar esta tabla de "votos" en una base de datos separada (ignorando los posibles problemas de integridad de datos) para dividirla de los datos "principales" en términos de almacenamiento y rendimiento?

(hago cuenta de que en 400MB mundo de hoy no es una tonelada? -, pero parece como mucho sólo para almacenar votos, sí)

Respuesta

7

En lo personal, siempre y cuando usted tiene buenos índices en su lugar, usted está hacerlo de la manera correcta. Dependiendo de su uso, para el rendimiento puede tratar de evitar golpear la tabla de votos almacenando la información secundaria de recuento, pero en general si debe realizar un seguimiento de QUIEN ha votado algo, debe hacerlo de la manera en que lo hizo.

No me molestaría en moverme a otra base de datos, si está REALMENTE preocupado en SQL Server podría crear un grupo de archivos por separado para mantenerlo ..... pero muy probablemente no sea necesario.

11

Bueno, sí, pero debe mirar la imagen más grande. Con un millón de piezas de CONTENIDO:

(Tamaño del contenido) >> (Tamaño de los votos): donde ">>" significa "mucho mayor".

Si tiene un millón de contenidos, puede ser un terabyte de datos donde los votos son de 400 MB. Gran cosa, ¿verdad?

También me gustaría añadir, si usted está preocupado por la escalabilidad, echa un vistazo a este blog:

http://highscalability.com/

4

Si necesita realizar un seguimiento de si un usuario ha votado por un artículo en particular, y si no son diferentes valores de voto (por lo tanto, 1 estrella a 5 estrellas, por ejemplo), entonces esto es lo más compacto posible.

No olvide que para velocidades de acceso razonables, necesitará indexar los datos (dos índices, probablemente uno con ContentID como columna principal, uno con ID de usuario como columna principal).

Deberá decidir si existe un motivo para no almacenar la tabla por separado de otras tablas. Lo que esto significa depende del DBMS que use: con Informix, la tabla estaría en la misma base de datos pero almacenada en un dbspace, y es posible que tenga los índices almacenados en otros dos espacios de base de datos.

4

Probablemente también querrá la ID del autor del contenido en la tabla, para una detección más fácil del abuso de votación. (Sí, esta es supuestamente información redundante.Una alternativa es la construcción regularmente un cuadro resumen para ver quién está votando sobre quién)

Por lo que vale la pena, la mesa perlmonks voto tiene el siguiente aspecto:.

`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 es el ID de contenido, IP se una dirección IP.)

0

Diría que necesita averiguar cómo se usarán estos votos y diseñar primero consultas específicas para su modelo de datos. Esto no es necesariamente un modelo de SQL. Si vienes del mundo de SQL, pasar por el tutorial oficial de MongoDB ayuda a despejar la mente para el comienzo.

Por ejemplo, si solo necesita almacenar y mostrar los votos de una sola página de problema, puede ser conveniente almacenar los votos en un solo campo de cadena del problema, que se verá como id1:id2:id3:. Suponiendo que todos los identificadores son de la misma longitud, hay algunas propiedades interesantes:

  1. Count todos los votos para la expedición:

    len(issue.votes)/len(id)

  2. Búsqueda Voté en el tema

    myid in issue.votes

  3. Encuentra todos los problemas que votaste en:

    select issue.id from issues where issue.votes contains(myid)

  4. encontrar la más votada cuestiones

    select issue.id from issues order by len(issue.votes) desc limit 10

Esta arquitectura permite evitar costosos cálculos de leer en estos casos específicos, pero la actualización de issue.votes el voto podría ser más caro que agregando una fila en una tabla. En este caso, 100 votos con 4 bytes por id + separador son cadenas de 500 bytes. En su variante propuesta, 100 votos son 800 bytes.

Descargo de responsabilidad: Nunca he implementado algo como esto, es solo una idea.

Cuestiones relacionadas