Consulta MySQL Join increíblemente lenta, explique que no ayuda

CONSULTA

explain select item_name, rating
from loyalty_visit_items
join loyalty_visits
on loyalty_visits.id = loyalty_visit_items.loyalty_visit_id
where loyalty_visits.parent_venue_id = 3794 

RESULTADOS

1   SIMPLE  loyalty_visits       ref  PRIMARY,parent_venue_id  parent_venue_id   4  const                      14388    
1   SIMPLE  loyalty_visit_items  ref  loyalty_visit_id         loyalty_visit_id  5  loyalty.loyalty_visits.id  12     Using where

Los índices parecen usarse correctamente, pero esta consulta generalmente nunca regresa antes de que se agote el tiempo de espera. Hay muy pocos datos en esta base de datos en relación con lo que necesita escalar para manejar, así que me pregunto qué pasa. Solo quiero esto para los elementos y mostrar una columna de la tabla de visitas de los padres junto con cada fila de elementos. ¿Hay una manera mucho mejor de hacer esta unión que me falta por completo?

**CREATE SHOW TABLE**
CREATE TABLE `loyalty_visits` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `loyalty_member_id` int(11) DEFAULT NULL,
  `venue_id` int(11) DEFAULT NULL,
  `parent_venue_id` int(11) NOT NULL DEFAULT '0',
  `visit_date` datetime DEFAULT NULL,
  `check_number` double(11,0) DEFAULT NULL,
  `code` varchar(16) DEFAULT NULL,
  `spend` decimal(12,2) DEFAULT NULL,
  `discount` decimal(11,0) DEFAULT NULL,
  `cover_count` int(11) DEFAULT NULL,
  `created_at` datetime DEFAULT NULL,
  `updated_at` datetime DEFAULT NULL,
  `sms_from_number` varchar(55) DEFAULT NULL,
  `rating` int(2) DEFAULT NULL,
  `server_id` int(11) DEFAULT NULL,
  `server_name` varchar(255) DEFAULT NULL,
  `terminal_id` int(11) DEFAULT NULL,
  `initial_text_sent` tinyint(1) DEFAULT NULL,
  `error` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `visit_date` (`visit_date`),
  KEY `parent_venue_id` (`parent_venue_id`),
  KEY `idx2` (`code`) USING HASH,
  KEY `venue_id_2` (`venue_id`),
  KEY `rating` (`rating`),
  KEY `idx3` (`loyalty_member_id`) USING HASH,
  KEY `spend` (`spend`),
  KEY `id` (`id`,`parent_venue_id`)
) ENGINE=Xeround DEFAULT CHARSET=latin1

preguntado el 03 de mayo de 12 a las 20:05

veamos algunos SHOW CREATE TABLE Salida, por favor. -

1 Respuestas

No estoy seguro de que los índices se estén utilizando con el máximo efecto. Un tipo de unión de ref No es genial. eq_ref y const son mucho mejores.

Puedes ver en el rows columna de la que MySQL espera leer un gran número de filas loyalty_visits. Pero como no encuentra filas por clave principal, no puede usar el índice agrupado. Esto significa que MySQL probablemente tenga que realizar muchas lecturas de disco, por lo que el índice apenas ayuda.

¿Cómo se puede optimizar esto? ¿Se puede reducir el número de filas que se deben leer? ¿Se puede utilizar un índice agrupado? ¿Se puede utilizar un índice de cobertura?

contestado el 03 de mayo de 12 a las 21:05

Creó un índice agrupado para los dos campos que se extraen de las visitas de lealtad (id y parent_venue_id), pero no pareció ayudar. - Karl

@Karl si está usando InnoDB, la clave principal es la , solamente índice agrupado posible. No puede crear nuevos índices agrupados. Mi punto era que debería intentar que su consulta use la clave principal si es posible. - mate fenwick

Quizás este sea solo el caso de que alcance mi límite de conocimiento de sql, pero se une en función de la clave principal (id). - Karl

@Karl sí, pero está filtrando según parent_venue_id. Y ese es el problema, porque aparentemente esa condición de filtro permite que pasen ~14k filas. Filas a las que no se puede acceder rápida y secuencialmente. Puede ver en los resultados de la explicación que MySQL consideró usar la clave principal, pero decidió no hacerlo. - mate fenwick

Supuse incorrectamente que tener ese filtro limitaría las filas que debían escanearse. ¿Cuál sería la forma correcta de limitar mi conjunto de resultados a filas con ese valor de parent_venue_id? Es una columna indexada. - Karl

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.