2009-02-08 6 views
5

Quiero comenzar a contar las veces que se ve una página web y, por lo tanto, necesito algún tipo de contador simple. ¿Cuál es el mejor método escalable para hacer esto?Cuál es la mejor manera de implementar un campo de contador en MySQL

Supongamos que tengo una tabla Frobs donde cada fila corresponde a una página - algunas opciones obvias son:

  1. tienen un campo NumViews unsigned int en la tabla Frobs que obtiene informado sobre cada vista mediante UPDATE Frobs SET NumViews = NumViews + 1 . Simple pero no tan bueno a escala como lo entiendo.

  2. Tenga una tabla separada FrobViews donde se inserta una nueva fila para cada vista. Para mostrar el número de vistas , debe hacer un simple SELECT COUNT(*) AS NumViews FROM FrobViews WHERE FrobId = '%d' GROUP BY FrobId. Esto no implica ninguna actualización, por lo que puede evitar el bloqueo de tablas en tablas MyISAM; sin embargo, el rendimiento de lectura se verá afectado si desea mostrar el número de vistas en cada página.

¿Cómo lo haces?

Hay algunos buenos consejos aquí: http://www.mysqlperformanceblog.com/2007/07/01/implementing-efficient-counters-with-mysql/ pero me gustaría escuchar las opiniones de la comunidad SO.

Estoy usando InnoDb por el momento, pero estoy interesado en las respuestas para InnoDb y MyISAM.

Respuesta

2

Tomaría su segundo enfoque y agregaría los datos en la tabla de su primera solución de forma regular. De esta forma, obtienes los avances de ambas soluciones. Para ser más claro: En cada golpe, inserta una fila en una tabla (nombrele hit_counters). Esta tabla solo tiene un campo (el pageid). Cada x segundos ejecuta un script (a través de un cronjob) que agrega los datos de la tabla hit_counters y los coloca en una segunda tabla (digamos 'hits'. Allí tiene dos campos: el pageid y el total de hits.

no estoy seguro, pero en mi humilde opinión no innodb no le ayuda mucho para la solución 1 si recibe muchos golpes en la misma página: innodb bloquea la fila mientras se actualiza por lo que todos los demás cambios a se retrasará esta fila

Dependiendo. ¿En qué programa está escrito usted también podría agrupar las actualizaciones contando en su aplicación y actualizando la base de datos solo cada x segundos? Esto solo funcionaría si usa un lenguaje de programación donde tiene un almacenamiento persistente (como Java Servlets pero no PHP)

3

Si la escalabilidad es más importante para usted que la precisión absoluta de las figuras, puede almacenar el conteo en su aplicación por un corto tiempo en lugar de ir a la base de datos en cada vista de página. Por ejemplo, solo actualice la base de datos cada 100 vistas .

Si su aplicación falla entre las actualizaciones de la base de datos, entonces, obviamente, perderá algunos de sus datos, pero si puede tolerar una cierta cantidad de imprecisión, este podría ser un enfoque útil.

0

Lo que hago, y puede no aplicarse a su escenario, es en el procedimiento almacenado que prepara/devuelve los datos que se muestran en la página, hago la actualización del contador de tabla al mismo tiempo que devuelve los datos - De esta forma, solo hay una llamada al servidor que obtiene los datos y actualiza el contador en la misma llamada.

Si no está utilizando SP, (o si no hay datos de la base de datos en su página) esta opción puede no estar disponible para usted, pero si lo está, es algo que debe tener en cuenta.

3

Insertar en una base de datos no es algo que desee hacer en vistas de página. Es probable que tenga problemas para actualizar sus bases de datos esclavas con todas las inserciones, ya que la replicación tiene un único hilo en MySQL.

En mi empresa atendemos 25 millones de páginas vistas por día y hemos adoptado un enfoque escalonado.

El contador de vista se almacena en una tabla separada con 2 columnas (profileId, viewCounter) ambos son enteros sin signo.

Para los elementos que se ven con poca frecuencia, actualizamos la tabla en la vista de página. Para los artículos que se ven con frecuencia, actualizamos MySQL aproximadamente 1/10 de las veces. Para ambos tipos, actualizamos Memcache en cada hit.
int Memcache::increment (string $key [, int $value = 1 ])

if (pageViews < 10000) { UPDATE page_view SET viewCounter=viewCounter+1 WHERE profileId = :? }

else if ((int)rand(10) == 1) { //UPDATE page_view SET viewCounter= ?:cache_value WHERE profileId = :? }

haciendo la cuenta (*) es muy ineficiente en InnoDB (MyISAM mantiene contar con estadísticas en el índice), pero MyISAM bloqueará la tabla en las lecturas reducir la simultaneidad. hacer un conteo() para 50,000 o 100,000 filas tomará mucho tiempo. Hacer una selección en un PK será muy rápido.

Si necesita más escalabilidad, es posible que desee consultar redis

Cuestiones relacionadas