2011-03-10 19 views
25

estoy usando MySQL 5.1, y tengo una consulta que es más o menos de la forma:¿EXISTS es más eficiente que COUNT (*)> 0?

select count(*) from mytable where a = "foo" and b = "bar"; 

En mi programa, lo único que se comprueba es si este es cero o distinto de cero. Si puedo convertir esto en:

select exists(select * from mytable where a = "foo" and b = "bar"); 

es MySQL suficientemente inteligente como para detener la búsqueda cuando llega a la primera? ¿O hay alguna otra forma de comunicarme a MySQL que mi intención es simplemente averiguar si algún registro coincide con esto, y no necesito un recuento exacto?

+5

Intente explicar en ambas consultas, debe obtener la respuesta. Puede publicar las salidas de explicación y la persona le ayudará a decodificar. – Zimbabao

+0

¡Es extremadamente improbable que MySQL sepa optimizar '' COUNT (*)> 0'! – Gabe

+4

El estándar ANSI dice que EXISTS es mejor porque no debe atravesar ni evaluar más allá de la "existencia" de una fila http://stackoverflow.com/questions/3271455/whats-the-best-to-check-if-item-exist -or-not-select-countidor-exist/3271464 # 3271464 – gbn

Respuesta

26

Sí, MySQL (de hecho, todos los sistemas de bases de datos que yo sepa) dejarán de procesarse cuando se devuelva una fila cuando se utiliza una función Exists.

Usted puede leer más en la documentación de MySQL: If a subquery returns any rows at all, EXISTS subquery is TRUE.

+0

No estoy seguro de que SQLite lo haga, junto con otras bases de datos simples. –

+1

@tc - Sí. Incluso SQLLite lo hace. Incluso acceso. Aún no me he encontrado con una base de datos que no lo haya hecho. – Thomas

+3

¿Por qué se bajó este valor? –

12

he ejecutar una prueba con 1.000 consultas. SELECT EXISTS fue aproximadamente un 25% más rápido que SELECT COUNT. Agregar limit 1 a SELECT COUNT no hizo ninguna diferencia.

+15

Agregar 'limit 1' a' select count' no haría ninguna diferencia, porque 'select count' devuelve una sola fila. :-) – Ken

1

No sé qué tan bien esto funciona para la optimización, pero debería funcionar funcionalmente igual que exists. La excepción es que no devolverá ninguna fila si no hay coincidencia.

SELECT true from mytable where a = "foo" and b = "bar" LIMIT 1; 
+0

¿No sería potencialmente devolver varias filas, cada una con un solo valor 'verdadero'? –

+0

Lo siento, olvidé el 'límite 1' en mi edición. Gracias por señalar eso! –

2

La forma más fiable es probablemente LIMIT 1, pero ese no es el punto.

Siempre que tenga un índice como CREATE INDEX mytable_index_a_b ON mytable (a,b), MySQL debe ser lo suficientemente inteligente como para devolver el recuento desde el índice y no tocar ninguna fila en absoluto. El beneficio de LIMIT 1 es probablemente insignificante.

Si no tiene un índice en (a, b), el rendimiento será terrible. LIMIT 1 puede hacer que sea significativamente menos terrible, pero igual será terrible.

+0

Bueno, heredé una base de código heredada, y el rendimiento * es * terrible. :-) – Ken

+0

@Ken: valdría la pena revisar la base de datos y agregar una gran pila de índices –

+0

Los índices obvios ya están presentes, y algunos de estos son tablas bastante grandes en las que el rendimiento de la inserción también es importante. – Ken

2

Esto también podría ser un enfoque.

select 1 from mytable where a = "foo" and b = "bar" limit 1; 

Esto no habría Traverce todos los registros que cumplen la condición en la que regresan sino más bien '1' después de la primera 'de favoritos. El inconveniente es que debe verificar el resultado, porque puede haber un registro vacío a cambio.

Cuestiones relacionadas