Tengo un par de duplicados en una base de datos que quiero inspeccionar, así que lo que hice para ver cuáles son duplicados, hice esto:
SELECT relevant_field
FROM some_table
GROUP BY relevant_field
HAVING COUNT(*) > 1
De esta manera, obtendré todas las filas con relevantes_campos que ocurran más de una vez. Esta consulta tarda milisegundos en ejecutarse.
Ahora, quería inspeccionar cada uno de los duplicados, por lo que pensé que podía SELECCIONAR cada fila en alguna_tabla con un campo relevante en la consulta anterior, así que me gustó esto:
SELECT *
FROM some_table
WHERE relevant_field IN
(
SELECT relevant_field
FROM some_table
GROUP BY relevant_field
HAVING COUNT(*) > 1
)
Esto resulta ser extremadamente lento por alguna razón (lleva minutos). ¿Qué está pasando exactamente aquí para que sea tan lento? relevante_campo está indexado.
Eventualmente intenté crear una vista "temp_view" desde la primera consulta (SELECT relevant_field FROM some_table GROUP BY relevant_field HAVING COUNT(*) > 1)
, y luego hice mi segunda consulta como esta:
SELECT *
FROM some_table
WHERE relevant_field IN
(
SELECT relevant_field
FROM temp_view
)
Y eso funciona bien. MySQL hace esto en algunos milisegundos.
¿Algún experto en SQL aquí que pueda explicar lo que está pasando?
Respuestas:
Reescribe la consulta en este
Creo que
st2.relevant_field
debe estar en la selección, porque de lo contrario lahaving
cláusula dará un error, pero no estoy 100% seguroNunca lo use
IN
con una subconsulta; Esto es notoriamente lento.Solo use
IN
con una lista fija de valores.Mas consejos
SELECT *
seleccione solo los campos que realmente necesita.relevant_field
para acelerar la equi-join.group by
en la clave principal.Solución general para el 90% de sus
IN (select
consultas.Usa este código
fuente
HAVING COUNT(*) > 1
. Suele ser más rápido en MySQL.st2.relevant_field
no lo estáNULL
(ya está incluido en laON
cláusula), no alterará el resultado.afield
que nunca lo seránull
, lo tengo. Graciasgroup by
está enst1.id
, no enst1.relevant_field
.La subconsulta se ejecuta para cada fila porque es una consulta correlacionada. Se puede hacer una consulta correlacionada en una consulta no correlacionada seleccionando todo desde la subconsulta, de esta manera:
La consulta final se vería así:
fuente
SELECT *
se necesita este ajuste.Subconsultas vs uniones
http://www.scribd.com/doc/2546837/New-Subquery-Optimizations-In-MySQL-6
fuente
He intentado su consulta en una de mis bases de datos y también he intentado reescribirla como una combinación para una subconsulta.
Esto funcionó mucho más rápido, ¡pruébalo!
fuente
Prueba esto
fuente
He formateado su consulta sql lenta con www.prettysql.net
Al usar una tabla tanto en la consulta como en la subconsulta, siempre debe tener un alias para ambos, así:
¿Eso ayuda?
fuente
En primer lugar, puede encontrar filas duplicadas y encontrar el recuento de filas que se utiliza cuántas veces y ordenarlo por un número como este;
después de eso, cree una tabla e inserte el resultado.
Finalmente, elimine las filas duplicadas. No es el inicio 0. Excepto el primer número de cada grupo, elimine todas las filas duplicadas.
fuente
a veces, cuando los datos crecen, mysql WHERE IN podría ser bastante lento debido a la optimización de la consulta. Intente usar STRAIGHT_JOIN para decirle a mysql que ejecute la consulta tal como está, por ej.
pero cuidado: en la mayoría de los casos, mysql optimizer funciona bastante bien, por lo que recomendaría usarlo solo cuando tenga este tipo de problema
fuente
Esto es similar a mi caso, donde tengo una tabla llamada
tabel_buku_besar
. Lo que necesito sonBuscando registro que tienen
account_code='101.100'
entabel_buku_besar
que secompanyarea='20000'
y también tienenIDR
comocurrency
Necesito obtener todos los registros de los
tabel_buku_besar
que tienen account_code igual que el paso 1 pero tienen el resultadotransaction_number
en el paso 1durante el uso
select ... from...where....transaction_number in (select transaction_number from ....)
, mi consulta se ejecuta extremadamente lenta y, a veces, causa un tiempo de espera de la solicitud o hace que mi aplicación no responda ...Intento esta combinación y el resultado ... no está mal ...
fuente
Creo que este es el más eficiente para encontrar si existe un valor, la lógica se puede invertir fácilmente para encontrar si un valor no existe (es decir, ES NULO);
* Reemplace relevante_campo con el nombre del valor que desea verificar existe en su tabla
* Reemplace primaryKey con el nombre de la columna de clave principal en la tabla de comparación.
fuente