2012-06-22 13 views
5

me pregunto si la cantidad de identificadores en una lista influirá en el rendimiento de consulta.SQL NO EN [lista de ID] (rendimiento)

consulta de ejemplo:

SELECT * FROM foos WHERE foos.ID NOT IN (2, 4, 5, 6, 7) 

Dónde (2, 4, 5, 6, 7) es una lista infinitamente creciente.

Y cuántos son demasiadas (en el contexto de la orden)?

ACTUALIZACIÓN: La razón por la que lo estoy pidiendo porque tengo dos db. Uno de ellos (de solo lectura) es la fuente de los artículos y el otro contiene elementos que procesa el operador. Cada vez que el operador solicita un nuevo artículo de solo lectura db, deseo excluir el artículo que ya está procesado.

+14

¿No debería haber etiquetado también este DB2? ¿Y qué diablos es "infinitamente ranurado"? ¿Debo estar asustado o emocionado? –

+0

@ AaronBertrand Lo sé, lo siento, pero me estaba molestando un poco considerando que el título dice Mysql, pero luego se agregó cada etiqueta RDBMS. – Taryn

+1

Su pregunta es un poco como preguntar "¿A qué velocidad es peligroso conducir en reversa?" En este caso, hay muchas maneras de llegar a lo que está preguntando, pero probablemente seríamos más útiles si proporcionara el motivo * real * para su solicitud. – swasheck

Respuesta

8

Sí, la cantidad de identificadores en la lista tendrá un impacto en el rendimiento. Un paquete de red sólo es tan grande, por ejemplo, y la base de datos tiene que analizar todo ese ruido y convertirla en una serie de:

WHERE foo.ID <> 2 
AND foo.ID <> 4 
AND foo.ID <> 5 
AND ... 

Debe tener en cuenta otras formas para que la consulta sabe acerca de este conjunto.

+4

para 'NOT IN' luego sería' AND' not' OR' Creo ... – JNK

+2

Sí, muy cierto. Pero no es el punto. :-) –

2

Aquí es reescritura loco de esa consulta que podría realizar un poco mejor

SELECT * FROM foos 
LEFT JOIN 
(
    SELECT 2 id UNION 
    SELECT 4 UNION 
    SELECT 5 UNION 
    SELECT 6 UNION 
    SELECT 7 
) NOT_IDS 
USING (id) WHERE NOT_IDS.id IS NULL; 

La subconsulta NOT_IDS funciona como lo demuestra el siguiente:

mysql> SELECT * FROM 
    -> (
    ->  SELECT 2 id UNION 
    ->  SELECT 4 UNION 
    ->  SELECT 5 UNION 
    ->  SELECT 6 UNION 
    ->  SELECT 7 
    ->) NOT_IDS; 
+----+ 
| id | 
+----+ 
| 2 | 
| 4 | 
| 5 | 
| 6 | 
| 7 | 
+----+ 
5 rows in set (0.00 sec) 

mysql> 
+0

¿Esto será traducido por MySQL de forma diferente a la consulta existente? Me imagino que la parte asombrosa seguirá construyendo esa 'UNIÓN' interna, dependiendo de la fuente de la lista. Pero en mi cabeza esto todavía se traduce a 'id <> 2 AND id <> 4 AND id <> 5 AND id <> 6 AND id <> 7' ... –

2

Sólo por diversión, y dada su actualización , Voy a sugerir una estrategia diferente:

Puedes unir mesas como ...

insert into db1.foos (cols) 
    select cols 
    from db2.foos src 
    left join db1.foos dst 
    on src.pk = dst.pk 
    where dst.othercolumn is null 

No estoy seguro de cómo el optimizador se encargará de esto o si va a ser más rápido (depende de su estrategia de indización, supongo) que lo que está haciendo.

0

Los db se encuentran en el mismo servidor? En caso afirmativo, puede hacer una consulta multi-db con una combinación de la izquierda y tomar las nulas. (aquí un ejemplo: Querying multiple databases at once). De lo contrario, puede hacer un procedimiento almacenado, pasar los identificadores con una cadena y dividirlos dentro con una expresión regular. Tengo un problema similar, pero dentro de un db en memoria y un db postgres. Afortunadamente mi situación es (en ...)