2009-01-17 23 views
9

Estoy tratando de encontrar una solución óptima para el siguiente problema: hay una necesidad de diseñar una base de datos (basada en postgres), el sistema de desencadenantes y contadores, que formará un sistema de consulta, actualización y almacenamiento eficiente de la información sobre "la cantidad de comentarios no leídos que existen en cada artículo (o entrada de blog, o algo similar) que se muestra en la página".Implementación de un sistema eficiente de contadores "sin leer comentarios"

Cada solución que llega a la cabeza, tiene algunas desventajas graves, ya sea en la consulta, o el almacenamiento, o la parte de actualización. Es decir. necesita demasiado almacenamiento o demasiadas actualizaciones o consultas demasiado costosas.

¿Qué hay de tu expiriencia? Tal vez hay una buena solución ya formada para este tipo de problemas?

Respuesta

8

Mantendría el esquema lo más simple posible, por lo que consultar será lo más simple posible. Esto generalmente también tiene los requisitos de almacenamiento más bajos. Por supuesto, configure índices para respaldar esta consulta.

Siguiente paso: medir el rendimiento! "Medir es saber". ¿Cuál es el tiempo de respuesta? ¿Cuál es la carga en el servidor? Siempre que el rendimiento sea aceptable, mantenga el esquema y la consulta simple. No sacrifique la capacidad de mantenimiento si no es absolutamente necesario: sus sucesores se lo agradecerán más adelante.

Si el rendimiento realmente es un problema, consulte la funcionalidad de almacenamiento en caché del marco que está utilizando para su aplicación. NO realizar una consulta siempre es más rápido que realizar una consulta optimizada.

4

Si realmente no tiene éxito dentro de su sobre de recursos, tal vez tenga que ajustar la experiencia del usuario. Tal vez sea suficiente almacenar la fecha del último acceso a un hilo.

4

No creo que el enfoque típico y normalizado lo deje con consultas ineficaces. Supongamos que tiene una tabla article_comments con PK (article_id, comment_id) y otra tabla comments_seen_by_user con PK (user_id, article_id, comment_id). Todo lo que necesita hacer es, para cada artículo que se indica en la página:

SELECT count(*) FROM article_comments ac 
WHERE article_id = ?    -- Parameter 
AND NOT EXISTS (
    SELECT 1 FROM comments_seen_by_user csbu 
    WHERE csbu.user_id = ?   -- Parameter 
    AND csbu.article_id = ac.article_id 
    AND csbu.comment_id = ac.comment_id 
) 

Si muestra 20 artículos en una página, se encontrará con la consulta por encima de 20 veces, y cada ejecución se usará un índice para tirar digamos 10-20 filas de article_comments, y la prueba de subconsulta es solo otra exploración de índice en comments_seen_by_user, por lo tanto, puede que tenga 20 * (20 * 2) = 800 búsquedas indexadas para mostrar una página determinada. Eso no es sudar a una base de datos moderna. Y probablemente no tenga en cuenta los planes de consulta aún mejores que PostgreSQL podría encontrar.

¿Ha probado esto y ha encontrado que le falta rendimiento? Si es así, mi primera suposición sería que no ha publicado VACUUM en un tiempo. De lo contrario, debo haber obtenido mis estimaciones para el número de artículos por página, o comentarios por artículo, incorrectos; actualice con más detalles en ese caso.

1

Responderé la segunda respuesta de j_random_hacker, solo evitaría almacenar el article_id en la tabla comments_seen_by_user dado que el comment_id debe ser globalmente único para cada comentario. También los índices tridimensionales (y de 2 a menos grados) siguen siendo lentos en PostgreSQL, así que trate de evitarlos.

No hay una manera realmente buena alrededor de una tabla de valores de user_id, comment_id para almacenar la información sobre los comentarios leídos, solo asegúrese de que tenga un índice único. Unos 10 millones de filas en dicha tabla no son ningún problema para PostgreSQL, siempre que pueda mantener el índice en la memoria.Puede hacer un seguimiento del tamaño del índice (número de páginas de 8 KB en el disco) con consultas a las tablas del sistema:

select relname,relpages from pg_class where relname='comments_seen_by_user_pkey'; 
+1

De acuerdo, globalmente únicos comment_ids son una buena idea. –

0

de que accediera a ir a dar un enfoque normalizado y ver si es resuelve. Normalmente debería. Sin embargo, también puede usar algunos INSERT-trigger en la tabla 'comment', que actualiza un contador de comentarios en la tabla base (es decir, artículo). Depende del perfil de uso de este sitio web: si los comentarios son en su mayoría leídos (en comparación con la adición de comentarios), la sobrecarga de un enfoque basado en el disparador debería amortizarse rápidamente. Si es un sitio que tiene una alta carga de comentarios, esto podría matar el rendimiento.

Me gustaría ir a una estructura de tabla simple, normalizada y agregar otra optimización más adelante, cuando tenga algún perfil de uso razonable.

+0

Su activador necesitaría actualizar filas de nUsers en una tabla con (user_id, article_id) (o alguna variación) como PK, ya que el historial de visualización de comentarios de cada usuario es independiente. Aún es factible. –

Cuestiones relacionadas