2009-10-08 17 views
23

Estoy ejecutando una consulta MYSQL en dos pasos. Primero, obtengo una lista de identificadores con una consulta, y luego recupero los datos para esos identificadores usando una segunda consulta a lo largo de las líneas SELECT * FROM data WHERE id in (id1, id2 ...). Sé que suena raro, pero lo he hecho de esta manera ya que las consultas son muy complicadas; el primero implica mucha geometría y trigonometría, el segundo muchas combinaciones diferentes. Estoy seguro de que podrían escribirse en una sola consulta, pero mi MYSQL no es lo suficientemente bueno para llevarlo a cabo.Rendimiento de MYSQL "IN"

Este enfoque funciona, pero no siente derecho; Además, me preocupa que no se escale. Por el momento estoy probando en una base de datos de 10,000 registros, con 400 ids en la cláusula "IN" (es decir, IN (id1, id2 ... id400)) y el rendimiento es bueno. Pero, ¿y si hay, digamos, 1,000,000 de registros?

¿Dónde están los cuellos de botella de rendimiento (velocidad, memoria, etc.) para este tipo de consulta? Cualquier idea sobre cómo refactorizar este tipo de consulta también puede ser impresionante. (por ejemplo, si vale la pena aumentar los procedimientos almacenados).

+0

¿Por qué no pone más detalles de su consulta? – RichardOD

+2

Supongo que no estoy preguntando sobre ninguna consulta en particular; más bien solo si es una buena idea en principio usar "IN" con una enorme lista de parámetros – Roy

Respuesta

19

A partir de un cierto número de registros, el predicado IN sobre un SELECT se vuelve más rápido que eso en una lista de constantes.

Ver este artículo en mi blog para comparación de rendimiento:

Si la columna utilizada en la consulta en la cláusula IN está indexado, así:

SELECT * 
FROM table1 
WHERE unindexed_column IN 
     (
     SELECT indexed_column 
     FROM table2 
     ) 

, luego esta consulta solo se optimiza a EXISTS (que usa solo una entrada para cada registro desde table1)

Desafortunadamente, MySQL no es capaz de hacer HASH SEMI JOIN o MERGE SEMI JOIN que aún son más eficientes (especialmente si se indexan las dos columnas).

+0

Ese artículo de blog es realmente útil, gracias. – Roy

+0

Esto realmente me ha ayudado también. Buen artículo. –

1

¿Por qué extrae primero los identificadores? Probablemente deberías simplemente unirte a las tablas. Si usa los identificadores para otra cosa, puede insertarlos en una tabla temporal antes y usar esta tabla para la unión.

+0

Sí, probablemente tengas razón. Primero hago el extracto porque la consulta de extracción es realmente complicada (muchas y muchas matemáticas, algunas subconsultas, etc.) y mi pequeño cerebro no pudo encontrar la manera de unirse, al mismo tiempo ... realmente me preguntaba si debería estar poniendo ese refactor cerca de la parte superior de mi lista de cosas por hacer o no! – Roy

+0

Entonces probablemente debería ponerlos en una tabla temporal. Eso sería más simple que obtenerlos y construir la cláusula in. Y Quassnoi dice que sería más rápido. –