2009-01-28 11 views

Respuesta

8

Si necesita un subconjunto de las columnas, le está dando mala ayuda al optimizador (no puede elegir para el índice, o no puede ir solamente para indexar, ...)

Algunas bases de datos pueden optar por recuperar solo datos de los índices. Esa cosa es muy útil y da una aceleración increíble. Ejecutar las consultas SELECT * no permite este truco.

De todos modos, desde el punto de vista de la aplicación no es una buena práctica.


Ejemplo de esto:

  • tiene una tabla T con 20 columnas (C1, C2, ..., C19 C20).
  • Usted tiene un índice en T para (C1, C2)
  • Usted hacer SELECT C1, C2 FROM T WHERE C1=123
  • El optimizador de tener toda la información en el índice, no tiene que ir a la tabla de datos

En cambio, si SELECT * FROM T WHERE C1=123, el optimizador necesita obtener todos los datos de las columnas, luego no se puede usar el índice en (C1, C2).

En combinaciones para tablas múltiples es de mucha ayuda.

+0

Pensé que los índices solo eran relevantes en las cláusulas JOIN, WHERE y GROUP BY. Alguien puede corregirme si me equivoco, pero ¿cómo las columnas en la cláusula de selección impiden que el optimizador seleccione un índice? – Juliet

+0

@Princess He actualizado la publicación con un ejemplo – FerranB

0

Supuestamente sí. Me dijeron de todo corazón en el trabajo que nunca debería usar SELECT *. De hecho, nuestra política es no usarlo porque a) significa que hay ambigüedad en lo que se utiliza y lo que está disponible simplemente mirando la consulta yb) es más lento ya que el servidor SQL tiene que encontrar cada columna que necesita y devolverlos .

Nunca he visto ninguna prueba de esto, sin embargo.

EDITAR: Además, si un procedimiento almacenado se compila en el servidor y utiliza SELECT *, cuando la estructura de la tabla cambia supuestamente no seleccionará volver las columnas de reciente introducción como compila SELECT SQL * hasta las columnas individuales.

+0

No hay una diferencia de plan de consulta entre los dos, pero si la tabla gana una columna adicional, la consulta no se ejecuta como originalmente lo hizo y devuelve más datos de los que probablemente sea necesario. – StingyJack

+0

El DB debe "buscar cada columna" ya sea que las nombre explícitamente o use *. En el caso en que desee todas las columnas, el rendimiento es idéntico. Sin embargo, no permitir * le obliga a pensar en lo que realmente necesita de la base de datos, que es una buena práctica. –

3

El único problema de rendimiento será si su aplicación solo necesita un subconjunto de los campos devueltos por select *. No hay diferencia de rendimiento en la base de datos ya que efectivamente son la misma cosa.

+0

+1 - A menudo se pasa por alto al responder a esta pregunta. 'SELECT col1, col2, col3' y' SELECT * 'son iguales si solo hay tres columnas llamadas col1, col2 y col3. – Fenton

2

No conozco el rendimiento informático, pero en términos de capacidad de lectura/mantenimiento (es decir, rendimiento humano) no utilizamos select * en mi tienda. Todo está explícitamente seleccionado.

1

Si se especifican todos los campos, entonces no, no debería haber una diferencia significativa en cuanto al rendimiento. Pero si solo quiere un par de campos específicos de una tabla con una docena de columnas, es más lento.

Hay problemas de legibilidad y mantenimiento con SELECT *. Tiene sentido usar nombres de campo específicos todo el tiempo, incluso si desea seleccionar todos los campos.

0

SELECCIONAR * se traduce para SELECCIONAR Campo1, Campo2 .... etc. antes de que se ejecute, por lo que efectivamente son la misma cosa. No hay diferencia en el rendimiento.

Sin embargo, la legibilidad y maintaiability son mejores cuando su SELECT Campo1, Campo2 ..

5

Cada vez que hace una selección *, no es puede ser una consulta adicional para obtener la lista de columnas. En entornos con grandes transacciones, este podría convertirse en en una sobrecarga visible, pero una vez de vez en cuando no hará ninguna diferencia.

Además, al insertar registros, nunca use select * en una inserción en caso de que se agreguen columnas.

+0

solo quería preguntarle: cuando especifica un campo en una tabla explícitamente en seleccionar, el servidor comprueba si el campo realmente existe, por lo que todavía hay una consulta adicional o estoy equivocado ? – empi

+0

Esto no es completamente exacto (bueno para algunas bases de datos al menos), la mayoría de las bases de datos de primer nivel preparan un plan para una consulta y lo almacenan en caché, así que si usas * o col lista la lista de columnas todavía se consulta en el momento de compilación del plan. La caché de consultas se invalida cuando ocurren cambios de DDL en la tabla. –

2

No soy un DBA, pero por lo que recuerdo haber aprendido de nuestro DBA, el razonamiento (al menos con SQL Server) es que los algoritmos de caché DB no almacenan en caché las consultas "*", pero si ejecutando la misma consulta con columnas exactas especificadas varias veces, se almacenará en caché muy bien.

Estoy seguro de que un DBA con más conocimiento podría entrar en los detalles exactos de cómo funciona el mecanismo de caché, pero es por eso que hay un golpe de rendimiento.

NOTA: El rendimiento de almacenamiento en caché solo funciona si la consulta se ejecutará varias veces, especialmente en un marco de tiempo pequeño, de lo contrario no vería ninguna diferencia de rendimiento.

0

Técnicamente, dependería del sistema de administración de bases de datos relacionales que esté utilizando. Creo que el rendimiento alcanzado sería de microsegundos. Si está absolutamente tratando de extraer el último bit de performace de su sistema, le diría que no los use.

Personalmente lo uso todo el tiempo.

11
+0

Esa publicación tiene más que ver con la mantenibilidad que con el rendimiento. Estoy de acuerdo con la respuesta a esa publicación que select * es un anti-patrón, pero esta pregunta fue sobre el rendimiento y si hay una diferencia o no. –

0

Si solo está utilizando un subconjunto de los campos, la diferencia de rendimiento puede ser considerable. Vea el siguiente ejemplo, que implica la recuperación de 1,411,771 filas de CScout 's analysis of the Linux code.

$ time sh -c "echo 'select * from IDS' | mysql cslinux >/dev/null" 
real 0m5.622s 
user 0m2.580s 
sys  0m0.532s 

$ time sh -c "echo 'select EID from IDS' | mysql cslinux >/dev/null" 
real 0m4.492s 
user 0m0.716s 
sys  0m0.096s 

Esto ni siquiera mide el impacto en el rendimiento del servidor.

+0

Agradable. Supongo que para obtener un resultado "justo", debe incluir más de una columna en la segunda declaración de selección. – splattne

+0

Él debería, de hecho, nombrar todos los campos de la tabla para hacer una prueba justa. – jmucchiello

+0

Con todos los campos especificados, no debe haber una diferencia de rendimiento perceptible (la sobrecarga es simplemente obtener los nombres de las columnas de la tabla). –

0

Si su incrustación sql en el código, entonces siempre debe utilizar la forma larga para mayor claridad, no para el rendimiento.Para consultas ad-hoc, la sintaxis de selección * ES ESENCIALMENTE no menos eficiente que la especificación de nombres de columna, a menos que tenga una cantidad masiva de columnas que no debería, a menos que esté desnormalizando.

¡Debo obtener 1 punto por usar 2 al menos en una oración y seguir teniendo sentido! :)

1

Rendimiento, no mucho. Es un poco torpe: en una tabla, por ejemplo, con 10 columnas, unidas en otras dos tablas o incluso más, particularmente con grandes conjuntos de resultados, SELECT * puede devolver docenas de columnas, a menudo con datos en su mayoría no utilizados o incluso inútiles. En términos del impacto en el SGBD, no habría mucho, pero toda esa información aún tiene que atravesar el cable de alguna manera; el ancho de banda de la red y las latencias consiguientes ciertamente se suman. Lo he visto de primera mano en entornos de gran volumen. Definitivamente importa

Aparte de los problemas de ancho de banda, también puede encontrar problemas ambiguos de nomenclatura de columnas (la eliminación de ambigüedades generalmente significa eliminar SELECT *, por lo que también puede hacerlo desde el principio), y también se considera buena práctica ser explícito sobre las necesidades del código dentro del código; Esto ayuda de muchas maneras: con la depuración, con la colaboración, etc.

0

SELECCIONAR * requiere que SQL encuentre todos los nombres de columna, sin embargo, este no es el mayor rendimiento alcanzado por una posibilidad remota.

El mayor golpe de rendimiento de una instrucción SELECT * es cuando está realizando una consulta que requiere un índice no agrupado para evaluar. Incluso si el índice no agrupado es un índice de cobertura de cada columna, SQL seguirá buscando la clave principal y obtendrá los valores del índice agrupado.

Además de esto, si solo necesita una o dos columnas, tiene que lidiar con el cuello de botella de red debido a que devuelve un conjunto de resultados más grande que el requerido.

0

Haré eco de lo que otros han dicho respecto a "seleccionar *" al recuperar una lista de columnas como parte del manejo de la solicitud. Por el contrario, también puede seleccionar columnas por ordinal, lo que ahorra aún más tiempo ya que el motor RDBMS ni siquiera necesita buscar la columna para determinar la posición de la columna que se va a recuperar. Encuentro esto muy útil para consultas agregadas.

Por ejemplo: select count (1) de ... frente select count (*) from ...

En este ejemplo, el RDBMS sólo necesita saber que necesita el recuento de la primera columna, y ZING, está apagado. En (desafortunadamente) recuento de selección más común (*), el RDBMS recupera una lista de todas las columnas, y luego verifica cada fila para determinar si es válida para contar (en lugar de validar solo la primera columna).

Esto funciona genial la mayor parte del tiempo. Estoy bastante seguro de que la mayoría de los sistemas DB cuentan los valores NULL en el recuento, pero debes tener cuidado con esto y verificar antes de asumir.

YMMV, nulo donde esté prohibido, etc.!

0

Rendimiento Esto siempre será malo si no NECESITA todas las columnas. Devolver más datos de los necesarios acelerará la base de datos y su ancho de banda lan/wan.

legibilidad Sabiendo que las columnas están en la vista, el procedimiento puede ser muy útil, SELECT * no es útil en absoluto y lo consideraría contraproducente.

* Pruebas Si realiza un cambio de esquema, todo el código que utilizan SELECT * dentro debe ser invalidado debido a las pruebas que escribe para comprobar los metadatos debe comprobar la salida de la vista, Proc.

* Por supuesto, suponiendo que tiene pruebas en su lugar como todo lo bueno de DB Dev debe tener :)

1

Si utiliza select * en un inscribe entonces usted está enviando automáticamente más información de la que necesita robaba el campo de unión (s) se repiten. Esto es una pérdida de tiempo de procesamiento y recursos de red y puede causar problemas de rendimiento. Además, al no especificar los campos, su aplicación puede romperse cuando se agregan nuevos campos, especialmente si se trata de campos que el usuario no debe ver pero que están ahí para auditar o procesar tipos de bases de datos. Seleccionar * en una inserción siempre es una mala idea, ya que en algún momento a lo largo de la línea algunas mujeres que no son tan inteligentes pueden cambiar el orden de las columnas en la tabla.

0

Estoy de acuerdo con casi todas las respuestas excepto ciertas afirmaciones de rendimiento. Si va a utilizar todas las columnas de la tabla, yo diría que la versión SELECT * es mucho más rápida. He aquí por qué:

Tome estas dos consultas en una mesa donde hay un índice único en (id, x):

SELECT x,y,z,w FROM tab WHERE id='abc' ORDER BY s 

SELECT x,y,z,w FROM tab WHERE id='abc' 
AND x in ('a','b','c','d','e','f','g','h',...) 
ORDER BY ('a','b','c','d','e','f','g','h',...) 

que es más rápido? Si la cláusula 'x in' nombra todos los valores para x en la tabla para id 'abc', entonces la primera consulta es probablemente más rápida. Ahora vamos a cambiar el nombre de estos campos:

SELECT field_name, field_type, field_offset, field_len 
FROM internal_field_catalog 
WHERE table_name = 'abc' 
ORDER BY field_order 

Así que cuando se recuperan los datos, el SELECT * permite que el motor para hacerlo (el equivalente a) un único establecimiento de memoria para mover los datos de fila para el conjunto de resultados y cuando se recuperan los datos de campo es probable que se seleccione más rápido.

Todo lo que digo es que hay un caso de borde donde SELECT * es perfectamente útil y probablemente más rápido. Una razón por la que siempre podría necesitar todas las columnas de una tabla es cuando se almacena la persistencia de objetos en un RDBMS (por alguna razón). Para cada regla general hay una excepción.

+0

Acepto esto, pero creo que otras razones para "no usarlo" contrarrestan este uso de ejemplo de SELECT *. – Coolcoder

2

Quizás. Depende en gran medida del motor de la base de datos, cómo almacena cosas, cuántas filas están regresando, cuántas otras columnas hay y los tamaños de las otras columnas.

Si está utilizando una base de datos basada en filas (es decir, la mayoría) que almacena todas las columnas juntas (casi todas lo hacen, excepto los BLOB que a menudo se almacenan por separado, especialmente los más grandes), entonces SELECT * tiene poco impacto en el servidor en sí; tiene que buscar toda la fila de todos modos.

Por otro lado, si envía los datos a través de una red (o incluso localmente, ya que afectará el tamaño de los almacenamientos intermedios utilizados, etc.), puede ser útil tener menos columnas, ya que habrá menos bytes para enviar de vuelta. Esta diferencia podría empequeñecerse de todos modos por el rendimiento del servidor si la consulta es de alguna manera difícil (por ejemplo, requiere IO).

Si tiene grandes manchas en las filas, SELECCIONAR * no es muy inteligente, de lo contrario, es poco probable que haga mucha diferencia, pero podría.

Existen algunos motores de base de datos "basados ​​en columnas" que se vuelven sorprendentes, son completamente diferentes; para ellos, "SELECT *" es un asesino de rendimiento total; asegúrate de evitarlo Lo más probable es que, si está utilizando uno, esté completamente consciente de esto (normalmente se usan para aplicaciones de datawarehouse muy grandes).

Para mí, la principal ventaja de no utilizar "SELECT *" es la capacidad de mantenimiento. No obtiene sorpresas cuando alguien agrega columnas adicionales a la mesa; su consulta "falla rápidamente" cuando alguien elimina una de las columnas que estaba usando. Hace que el código sea más autodocumentado ya que alguien puede ver de manera informal qué columnas quiere.

Cuestiones relacionadas