¿Por qué SELECT* se considera perjudicial?

Resuelto Theodore R. Smith asked hace 14 años • 16 respuestas

¿ Por qué es SELECT *una mala práctica? ¿No significaría menos código para cambiar si agregaras una nueva columna que quisieras?

Entiendo que SELECT COUNT(*)es un problema de rendimiento en algunas bases de datos, pero ¿qué pasaría si realmente quisieras todas las columnas?

Theodore R. Smith avatar Sep 04 '10 05:09 Theodore R. Smith
Aceptado

Realmente hay tres razones principales:

  • Ineficiencia en el traslado de datos al consumidor. Cuando SELECCIONA *, a menudo recupera más columnas de la base de datos de las que su aplicación realmente necesita para funcionar. Esto hace que se muevan más datos desde el servidor de la base de datos al cliente, lo que ralentiza el acceso y aumenta la carga en sus máquinas, además de tomar más tiempo para viajar a través de la red. Esto es especialmente cierto cuando alguien agrega nuevas columnas a tablas subyacentes que no existían y no eran necesarias cuando los consumidores originales codificaron su acceso a los datos.

  • Problemas de indexación. Considere un escenario en el que desee ajustar una consulta a un alto nivel de rendimiento. Si usara * y devolviera más columnas de las que realmente necesitaba, el servidor a menudo tendría que realizar métodos más costosos para recuperar sus datos de lo que lo haría de otro modo. Por ejemplo, no podría crear un índice que simplemente cubriera las columnas de su lista SELECT, e incluso si lo hiciera (incluidas todas las columnas [ temblor ]), el siguiente tipo que viniera y agregara una columna al índice subyacente table haría que el optimizador ignorara su índice de cobertura optimizado y probablemente encontraría que el rendimiento de su consulta disminuiría sustancialmente sin ninguna razón aparente.

  • Problemas de vinculación. Cuando SELECCIONA *, es posible recuperar dos columnas con el mismo nombre de dos tablas diferentes. Esto a menudo puede bloquear a su consumidor de datos. Imagine una consulta que une dos tablas, las cuales contienen una columna llamada "ID". ¿Cómo sabría un consumidor cuál es cuál? SELECT * también puede confundir las vistas (al menos en algunas versiones de SQL Server) cuando las estructuras de las tablas subyacentes cambian: la vista no se reconstruye y los datos que regresan pueden no tener sentido . Y lo peor de esto es que puedes encargarte de nombrar tus columnas como quieras, pero el siguiente que aparezca puede que no tenga forma de saber que tiene que preocuparse por agregar una columna que colisionará con tu ya desarrollado. nombres.

Pero no todo es malo para SELECT *. Lo uso generosamente para estos casos de uso:

  • Consultas ad hoc. Cuando intento depurar algo, especialmente en una tabla estrecha con la que quizás no esté familiarizado, SELECT * suele ser mi mejor amigo. Me ayuda a ver qué está pasando sin tener que investigar mucho sobre cuáles son los nombres de las columnas subyacentes. Esto se convierte en una "ventaja" mayor cuanto más largos se vuelven los nombres de las columnas.

  • Cuando * significa "una fila". En los siguientes casos de uso, SELECT * está bien, y los rumores de que afecta el rendimiento son solo leyendas urbanas que pueden haber tenido cierta validez hace muchos años, pero ya no:

    SELECT COUNT(*) FROM table;
    

    en este caso, * significa "contar las filas". Si usara un nombre de columna en lugar de * , contaría las filas donde el valor de esa columna no fuera nulo . COUNT(*), para mí, realmente resalta el concepto de que estás contando filas y evitas casos extremos extraños causados ​​por la eliminación de NULL de tus agregados.

    Lo mismo ocurre con este tipo de consulta:

    SELECT a.ID FROM TableA a
    WHERE EXISTS (
        SELECT *
        FROM TableB b
        WHERE b.ID = a.B_ID);
    

    en cualquier base de datos que se precie, * simplemente significa "una fila". No importa lo que pongas en la subconsulta. Algunas personas usan el ID de b en la lista SELECT, o usarán el número 1, pero en mi opinión, esas convenciones no tienen sentido. Lo que quieres decir es "cuenta la fila", y eso es lo que * significa. La mayoría de los optimizadores de consultas que existen son lo suficientemente inteligentes como para saber esto. (Aunque, para ser honesto, sólo que esto es cierto con SQL Server y Oracle).

Dave Markle avatar Sep 03 '2010 22:09 Dave Markle

El carácter de asterisco, "*", en la instrucción SELECT es una abreviatura de todas las columnas de las tablas involucradas en la consulta.

Actuación

La *taquigrafía puede ser más lenta porque:

  • No todos los campos están indexados, lo que obliga a realizar un análisis completo de la tabla (menos eficiente)
  • Lo que guarda para enviar SELECT *por cable corre el riesgo de un escaneo completo de la tabla
  • Devolver más datos de los necesarios
  • Devolver columnas finales utilizando tipos de datos de longitud variable puede generar una sobrecarga de búsqueda

Mantenimiento

Cuando usas SELECT *:

  • Alguien que no esté familiarizado con el código base se vería obligado a consultar la documentación para saber qué columnas se devuelven antes de poder realizar cambios competentes. Hacer que el código sea más legible, minimizar la ambigüedad y el trabajo necesario para las personas que no están familiarizadas con el código ahorra más tiempo y esfuerzo a largo plazo.
  • Si el código depende del orden de las columnas, SELECT *ocultará un error que espera ocurrir si se cambia el orden de las columnas de una tabla.
  • Incluso si necesita todas las columnas en el momento en que se escribe la consulta, es posible que ese no sea el caso en el futuro.
  • el uso complica la elaboración de perfiles

Diseño

SELECT *es un antipatrón :

  • El propósito de la consulta es menos obvio; las columnas utilizadas por la aplicación son opacas
  • Rompe la regla de modularidad sobre el uso de tipificación estricta siempre que sea posible. Lo explícito es casi universalmente mejor.

¿Cuándo se debe utilizar "SELECT *"?

Es aceptable usarlo SELECT *cuando existe la necesidad explícita de cada columna de las tablas involucradas, a diferencia de cada columna que existía cuando se escribió la consulta. La base de datos expandirá internamente el * en la lista completa de columnas; no hay diferencia de rendimiento.

De lo contrario, enumere explícitamente cada columna que se utilizará en la consulta, preferiblemente mientras usa un alias de tabla.

OMG Ponies avatar Sep 03 '2010 22:09 OMG Ponies

Incluso si desea seleccionar todas las columnas ahora, es posible que no desee seleccionar todas las columnas después de que alguien agregue una o más columnas nuevas. Si escribe la consulta, SELECT *corre el riesgo de que en algún momento alguien agregue una columna de texto que haga que su consulta se ejecute más lentamente aunque en realidad no necesite esa columna.

¿No significaría menos código para cambiar si agregaras una nueva columna que quisieras?

Lo más probable es que si realmente desea utilizar la nueva columna, de todos modos tendrá que realizar muchos otros cambios en su código. Sólo estás guardando , new_column, sólo unos pocos caracteres de escritura.

Mark Byers avatar Sep 03 '2010 22:09 Mark Byers

Si realmente desea cada columna, no he visto una diferencia de rendimiento entre seleccionar (*) y nombrar las columnas. El controlador para nombrar las columnas podría ser simplemente ser explícito sobre qué columnas espera ver en su código.

Sin embargo, a menudo no desea todas las columnas y select(*) puede resultar en trabajo innecesario para el servidor de la base de datos y en la necesidad de pasar información innecesaria a través de la red. Es poco probable que cause un problema notable a menos que el sistema se utilice mucho o la conectividad de la red sea lenta.

brabster avatar Sep 03 '2010 22:09 brabster

Si nombra las columnas en una instrucción SELECT, se devolverán en el orden especificado y, por lo tanto, se podrá hacer referencia a ellas de forma segura mediante un índice numérico. Si usa "SELECT *", puede terminar recibiendo las columnas en una secuencia arbitraria y, por lo tanto, solo podrá usar las columnas de manera segura por su nombre. A menos que sepa de antemano qué querrá hacer con cualquier columna nueva que se agregue a la base de datos, la acción correcta más probable es ignorarla. Si va a ignorar cualquier columna nueva que se agregue a la base de datos, no hay ningún beneficio en recuperarla.

supercat avatar Sep 03 '2010 22:09 supercat