2010-01-29 11 views
5

Tengo una consulta de cálculo de recuento que estoy ejecutando miles de veces en mi aplicación Rails, una vez por cada cliente en la base de datos.Rails MySQL confusión de tiempo de consulta

Cuando ejecuto la consulta en mi cliente MySQL con el caché de consultas desactivado, la consulta tarda más de 1ms.

Sin embargo, cuando ejecuto mi tarea desde la consola de Rails con salida de consulta habilitada, me he dado cuenta de que después de las primeras consultas que son muy rápidas el tiempo aumenta súbitamente de menos de 1ms a aproximadamente 180ms para el resto del consultas.

He reducido el innodb_buffer_pool_size para ver un cambio en el comportamiento pero no he notado nada.

Aquí está la salida de la consola:

EmailCampaignReport::Open Columns (143.2ms) SHOW FIELDS FROM `email_campaign_report_opens` 
    SQL (0.3ms) SELECT count(*) AS count_all FROM `email_campaign_report_opens` WHERE (customer_id = 332330) 
    SQL (0.2ms) SELECT count(*) AS count_all FROM `email_campaign_report_opens` WHERE (customer_id = 333333) 
    SQL (0.2ms) SELECT count(*) AS count_all FROM `email_campaign_report_opens` WHERE (customer_id = 332661) 
    SQL (0.1ms) SELECT count(*) AS count_all FROM `email_campaign_report_opens` WHERE (customer_id = 332326) 
    SQL (0.1ms) SELECT count(*) AS count_all FROM `email_campaign_report_opens` WHERE (customer_id = 332665) 
    SQL (0.2ms) SELECT count(*) AS count_all FROM `email_campaign_report_opens` WHERE (customer_id = 336027) 
    SQL (0.2ms) SELECT count(*) AS count_all FROM `email_campaign_report_opens` WHERE (customer_id = 333001) 
    SQL (0.2ms) SELECT count(*) AS count_all FROM `email_campaign_report_opens` WHERE (customer_id = 331983) 
    SQL (0.1ms) SELECT count(*) AS count_all FROM `email_campaign_report_opens` WHERE (customer_id = 332668) 
    SQL (0.1ms) SELECT count(*) AS count_all FROM `email_campaign_report_opens` WHERE (customer_id = 332316) 
    SQL (0.1ms) SELECT count(*) AS count_all FROM `email_campaign_report_opens` WHERE (customer_id = 332325) 
    SQL (0.1ms) SELECT count(*) AS count_all FROM `email_campaign_report_opens` WHERE (customer_id = 331995) 
    SQL (0.2ms) SELECT count(*) AS count_all FROM `email_campaign_report_opens` WHERE (customer_id = 334007) 
    SQL (0.2ms) SELECT count(*) AS count_all FROM `email_campaign_report_opens` WHERE (customer_id = 333326) 
    SQL (0.1ms) SELECT count(*) AS count_all FROM `email_campaign_report_opens` WHERE (customer_id = 332998) 
    SQL (183.9ms) SELECT count(*) AS count_all FROM `email_campaign_report_opens` WHERE (customer_id = 334673) 
    SQL (183.7ms) SELECT count(*) AS count_all FROM `email_campaign_report_opens` WHERE (customer_id = 336751) 
    SQL (183.6ms) SELECT count(*) AS count_all FROM `email_campaign_report_opens` WHERE (customer_id = 333334) 
    SQL (186.3ms) SELECT count(*) AS count_all FROM `email_campaign_report_opens` WHERE (customer_id = 332663) 
    SQL (183.7ms) SELECT count(*) AS count_all FROM `email_campaign_report_opens` WHERE (customer_id = 332328) 
    SQL (186.3ms) SELECT count(*) AS count_all FROM `email_campaign_report_opens` WHERE (customer_id = 332659) 

No es un índice en la columna de la customer_id en esa tabla.

¿Alguien ha recibido alguna sugerencia de por qué esto estaría sucediendo?

Gracias

+0

¿Puedes publicar el esquema de tu tabla para que podamos ver el índice, etc.? – UltimateBrent

Respuesta

4

¿Por qué no ejecutar solo una consulta?

SELECT customer_id, count(*) AS count_all FROM `email_campaign_report_opens` GROUP BY customer_id; 

Si tiene tantos registros que están preocupados por regresar a todos a continuación, lo hacen en lotes, pero simplemente no entiende por qué se realmente quiere ejecutar esta consulta para cada cliente.

+0

¡por qué no pensé en eso! Gracias hombre. – johnnymire

+0

Me alegro de que funcione para usted. Es fácil pensar en hacer todo con objetos e iteradores en ActiveRecord, pero a veces un poco de SQL es lo mejor. –

0

¿Esto sucede en sus rieles aplicación también, o tiene esto sólo sucede cuando se ejecuta en la consola? Además, ¿está utilizando un cliente como Aptana o está ejecutando esto en un shell?

+0

Esto se ejecutó en un shell y ocurre en la aplicación Rails también. – johnnymire

0

¿Qué versión de Rails es esto? Dependiendo de su versión y su código de Ruby/Rails, puede estar guardando en caché una gran cantidad de datos sin usarlo, y después de un tiempo tiene que hacer la recolección de basura antes de obtener nuevos datos, lo que puede explicar la demora. Esto es una suposición, te lo advierto.

+0

It's Rails versión 2.3.2 – johnnymire

0

¿No tendría sentido agregar un counter cache a la asociación (léase: agregue un email_campaign_report_opens_count a su modelo Customer)? Por supuesto, debe inicializar los contadores durante la migración, pero luego debe ser realmente rápido e incluso no necesita tocar la tabla asociada mientras recorre la tabla de clientes.

+0

Buena sugerencia. Esto era casi lo que estaba haciendo, tengo un campo de recuento similar en el modelo de cliente que estaba siendo actualizado por esta secuencia de comandos obteniendo todos los conteos. La actualización de la memoria caché del contador a medida que se crean las asociaciones puede ser mejor. Todavía tendrá el problema de velocidad de consulta durante la migración inicial, pero al menos es una sola vez. – johnnymire

Cuestiones relacionadas