¿Por qué SELECT * sería magnitudes más rápido que SELECT foo?

28

Considere una tabla de valores y hashes, así:

+------------+----------+------+-----+---------+----------------+
| Field      | Type     | Null | Key | Default | Extra          |
+------------+----------+------+-----+---------+----------------+
| id         | int(11)  | NO   | PRI | NULL    | auto_increment |
| val        | char(9)  | NO   |     | NULL    |                |
| val_hashed | char(50) | YES  |     | NULL    |                |
+------------+----------+------+-----+---------+----------------+

La siguiente consulta finaliza en 0.00 segundos:

SELECT * FROM hashes ORDER BY 1 DESC LIMIT 1;

Sin embargo, esta consulta toma 3 min 17 segundos:

SELECT val FROM hashes ORDER BY 1 DESC LIMIT 1;

Veo que mientras se ejecuta la consulta, la lista de procesos la muestra como estado Sorting result. La situación es completamente reproducible. Tenga en cuenta que hay otro proceso que realiza INSERToperaciones en la tabla continuamente.

¿Por qué la consulta más específica tardaría más en ejecutarse que la *consulta? Siempre he creído que las *consultas deben evitarse específicamente por razones de rendimiento.

dotancohen
fuente
77
Las primeras declaraciones probablemente usan el índice de clave primaria idpara encontrar la primera fila. El segundo necesita ordenar el resultado completo en la valcolumna (sin indexar) .
a_horse_with_no_name
8
La ORDER BY NUMBERsintaxis es bastante propensa a errores.
Usr
2
Agregando a su último comentario, SELECT *combinado con un índice de columna en ORDER BYestá ofuscando qué columna se está ordenando, otra razón para evitar *s ...
lc.
@lc., ¿Qué quieres decir?
Pacerier
@Pacerier Quiero decir *que no es explícito. Así que decir "dame todas las columnas y ordenar por la tercera" es tan determinista como decir "ve al supermercado y dime cuántos semáforos pasaste"
lc.

Respuestas:

33

La frase se ORDER BY 1refiere a diferentes columnas; en el primero será id, en el segundo val. Como ides la clave, se indexará y order byserá una cantidad de trabajo trivial. Sin order by valembargo, para que el sistema tenga que recuperar cada fila, ordenar la tabla completa valy luego elegir solo una de esas filas.

Cambia ambas consultas order by idy creo que tus tiempos de ejecución serán casi idénticos.

Michael Green
fuente
3
A veces las preguntas más difíciles son aquellas que simplemente nos están mirando a la cara. Gracias Michael!
dotancohen
7

MG explica bien la diferencia de rendimiento en su consulta. Voy a abordar esto:

Siempre he creído que las consultas * deben evitarse específicamente por razones de rendimiento.

select *no conlleva sanciones particulares por sí mismo, es problemático cuando se usa incorrectamente. En una consulta de una sola tabla, funciona bien. ahora une esa tabla a otra con 20 columnas, y luego agrega combinaciones a otras 5 tablas con muchas columnas cada una. AHORA es un problema. También lo son las personas que enseñan banda ancha, "nunca hacen X" sin explicar por qué.

Paul
fuente
3
SELECT *podría ser un problema incluso para una consulta de una sola tabla. Por ejemplo, SELECT * FROM hashes ORDER BY val;probablemente hará un escaneo completo de la tabla y luego una ordenación, mientras SELECT val FROM hashes ORDER BY val;que solo hará un escaneo de índice completo, y no ordenará (suponiendo que exista un índice en val). Por lo tanto, nunca está de más seleccionar solo los resultados que necesitamos.
ypercubeᵀᴹ
¿Asumo que has visto esto? sqlblog.com/blogs/aaron_bertrand/archive/2009/10/10/…
Max Vernon
@ypercube, ¿esto ocurre incluso si nuestra select(*)única se utiliza como sub -seleccione? Dado que es una selección integrada, ¿no sería MySQL lo suficientemente inteligente como para descubrir las columnas reales que deben seleccionarse?
Pacerier
@Pacerier mysql optimizer tiene diferentes niveles de "inteligencia", dependiendo de la versión que esté utilizando. En general, era bastante tonto con respecto a las subconsultas anidadas, así que todo lo que pudiste para ayudarlo, fue bueno.
ypercubeᵀᴹ
@ypercube, Ah, si tan solo es tan inteligente como pgsql.
Pacerier