2012-04-01 15 views
8

Parece que estoy un poco atascado. Es una consulta bastante sencilla.Ayuda de Mysql necesaria para optimizar grupo por sub consulta

Si ejecuto las consultas por separado, no es tan lento, pero cuando las combino es muy lento.

No estoy seguro de cómo optimizarlo. Cualquier ayuda sería muy apreciada. Básicamente, solo quiero mostrar varios reembolsos. Entonces, donde faultid existe más de una vez.

SELECT 
    r.* 
FROM 
    faultrefunds_v2 r 
WHERE 
    r.id IN (SELECT r1.id 
      FROM faultrefunds_v2 r1 
      GROUP BY faultid 
      HAVING count(r1.faultid) > 1); 

Los resultados de explicar se han unido como una imagen

enter image description here

+0

Is r.id the primar y la clave? –

+0

sí, y faultid es la clave externa –

+0

Creo que la consulta que escribió no responde la pregunta. Esto se debe a que una vez que haya agrupado por faultid, solo devolverá un r.id por ese faultid. –

Respuesta

1

supongo, esto califica más bien como una re-escritura que como una optimización, pero esto es lo que probaría en su lugar, de todos modos:

SELECT 
    r.* 
FROM faultrefunds_v2 r 
WHERE EXISTS (
    SELECT * 
    FROM faultrefunds_v2 r1 
    WHERE r1.faultid = r.faultid 
    AND r1.id <> r.id 
); 
+0

esto funcionó también. –

+0

¿por qué es esto mucho más rápido que la consulta que escribí? se ven bastante similares? –

+1

Su consulta utiliza la agrupación, que es una operación relativamente costosa, para empezar. Además, se supone que una subconsulta de ese tipo escanea toda la tabla para construir el conjunto de filas para que coincida. Mi consulta, por otro lado, usa una semi-unión (en la forma del predicado 'EXISTS'). En una semi unión, se buscan las coincidencias para una fila tan pronto como se encuentre al menos una, lo que se puede adivinar puede acelerar la consulta de forma espectacular en los casos en que existen muchas coincidencias para algunas/la mayoría de las filas. –

1

Creo que su consulta no está respondiendo a la pregunta. Según tengo entendido, primero debes obtener todos los faultid que tengan más de un id asociado (fila en la tabla). Y luego obtenga todas esas filas (no solo el faultId).

Prueba esto:

select * from faultrefunds_v2 
where faultId in (
    select faultId from faultrefunds_v2 
    group by faultId 
    having count(*) > 1 
) 
+0

Creo que esto es una mejora en mi consulta, es más lógico y explicativo. Pero todavía es bastante lento. dado que +1 –

2

IN cláusula de la forma en que solía sería muy lento, utilice JOIN lugar:

SELECT r.* FROM ( 
    SELECT r1.id AS id 
    FROM faultrefunds_v2 r1 
    GROUP BY faultid 
    HAVING count(r1.faultid) > 1 
) AS ids 
LEFT JOIN faultrefunds_v2 AS r 
ON(ids.id = r.id) 
+0

esto funciona, es muy rápido. ¿Puedes explicar por qué la cláusula IN es lenta con la forma en que la utilicé para evitar volver a hacerlo? –

+1

MySql generalmente no indexa los elementos dentro de la cláusula IN por lo que debe comparar el id de cada fila en la tabla 'r' con todos los identificadores encontrados en la sub consulta cada vez. En mi método, MySql encuentra todos los ID apropiados una vez y luego recupera la fila completa para cada ID en la consulta externa muy rápidamente usando el índice. – nobody

+0

Esta respuesta es la respuesta correcta junto con la respuesta de Andiry M. No puedo aceptar dos respuestas (aunque creo que es posible tener dos respuestas correctas pero diferentes para la misma pregunta). –

Cuestiones relacionadas