Escuché que SELECT *
generalmente es una mala práctica usar al escribir comandos SQL porque es más eficiente para las SELECT
columnas que necesita específicamente.
Si necesito SELECT
cada columna de una tabla, ¿debería usar
SELECT * FROM TABLE
o
SELECT column1, colum2, column3, etc. FROM TABLE
¿La eficiencia realmente importa en este caso? Creo que SELECT *
sería más óptimo internamente si realmente necesita todos los datos, pero lo digo sin una comprensión real de la base de datos.
Tengo curiosidad por saber cuál es la mejor práctica en este caso.
ACTUALIZACIÓN: Probablemente debería especificar que la única situación en la que realmente me gustaría hacer una SELECT *
es cuando selecciono datos de una tabla donde sé que todas las columnas siempre tendrán que recuperarse, incluso cuando se agregan nuevas columnas.
Sin embargo, dadas las respuestas que he visto, esto todavía parece una mala idea y SELECT *
nunca debería usarse por muchas más razones técnicas de las que nunca he pensado .
Respuestas:
Una razón por la que es mejor seleccionar columnas específicas es que aumenta la probabilidad de que SQL Server pueda acceder a los datos de los índices en lugar de consultar los datos de la tabla.
Aquí hay una publicación que escribí al respecto: la verdadera razón por la que las consultas de selección son una mala cobertura de índice
También es menos frágil cambiar, ya que cualquier código que consuma los datos obtendrá la misma estructura de datos, independientemente de los cambios que realice en el esquema de la tabla en el futuro.
fuente
vs
all_column_names) mientras tenemos miles de filas y realizamos SELECT con índice (en la cláusula WHERE)?Dada su especificación de que está seleccionando todas las columnas, hay poca diferencia en este momento . Sin embargo, tenga en cuenta que los esquemas de la base de datos cambian. Si usa
SELECT *
, obtendrá columnas nuevas agregadas a la tabla, aunque con toda probabilidad, su código no está preparado para usar o presentar esos nuevos datos. Esto significa que está exponiendo su sistema a cambios inesperados de rendimiento y funcionalidad.Puede estar dispuesto a descartar esto como un costo menor, pero tenga en cuenta que las columnas que no necesita aún deben ser:
El elemento n. ° 1 tiene muchos costos ocultos, incluida la eliminación de algunos índices de cobertura potenciales, lo que causa cargas de páginas de datos (y agitación de la memoria caché del servidor), incurriendo en bloqueos de fila / página / tabla que de otro modo podrían evitarse.
Equilibre esto con los ahorros potenciales de especificar las columnas versus an
*
y los únicos ahorros potenciales son:Para el elemento 1, la realidad es que va a agregar / cambiar el código para usar cualquier columna nueva que pueda agregar de todos modos, por lo que es un lavado.
Para el elemento 2, la diferencia rara vez es suficiente para empujarlo a un tamaño de paquete diferente o un número de paquetes de red. Si llega al punto donde el tiempo de transmisión de la declaración SQL es el problema predominante, es probable que primero necesite reducir la velocidad de las declaraciones.
Para el ítem 3, NO hay ahorros ya que la expansión del
*
tiene que ocurrir de todos modos, lo que significa consultar el esquema de la (s) tabla (s) de todos modos. Siendo realistas, enumerar las columnas incurrirá en el mismo costo porque deben validarse contra el esquema. En otras palabras, este es un lavado completo.Para el elemento 4, cuando especifica columnas específicas, la memoria caché del plan de consulta podría aumentar, pero solo si se trata de diferentes conjuntos de columnas (que no es lo que ha especificado). En este caso, desea entradas de caché diferentes porque desea planes diferentes según sea necesario.
Entonces, todo se reduce, debido a la forma en que especificó la pregunta, al problema de la resistencia ante eventuales modificaciones del esquema. Si está grabando este esquema en ROM (sucede), entonces
*
es perfectamente aceptable.Sin embargo, mi pauta general es que solo debe seleccionar las columnas que necesita, lo que significa que a veces parecerá que las está pidiendo todas, pero los DBA y la evolución del esquema significan que pueden aparecer algunas columnas nuevas que podrían afectar en gran medida la consulta .
Mi consejo es que SIEMPRE SELECCIONE columnas específicas . Recuerda que te vuelves bueno en lo que haces una y otra vez, así que solo tienes la costumbre de hacerlo bien.
Si se pregunta por qué un esquema podría cambiar sin cambiar el código, piense en términos de registro de auditoría, fechas de vigencia / caducidad y otras cosas similares que los DBA agregan para problemas de cumplimiento sistemáticamente. Otra fuente de cambios disimulados son las desnormalizaciones para el rendimiento en otras partes del sistema o campos definidos por el usuario.
fuente
Solo debe seleccionar las columnas que necesita. Incluso si necesita todas las columnas, es mejor enumerar los nombres de las columnas para que el servidor SQL no tenga que consultar las columnas de la tabla del sistema.
Además, su aplicación podría romperse si alguien agrega columnas a la tabla. Su programa obtendrá columnas que tampoco esperaba y es posible que no sepa cómo procesarlas.
Aparte de esto, si la tabla tiene una columna binaria, la consulta será mucho más lenta y usará más recursos de red.
fuente
Hay cuatro grandes razones que
select *
es malo:La razón práctica más importante es que obliga al usuario a conocer mágicamente el orden en que se devolverán las columnas. Es mejor ser explícito, lo que también lo protege contra el cambio de tabla, que se divide muy bien en ...
Si un nombre de columna que está usando cambia, es mejor detectarlo temprano (en el punto de la llamada SQL) en lugar de cuando está tratando de usar la columna que ya no existe (o que ha cambiado su nombre, etc.) )
Listar los nombres de las columnas hace que su código sea mucho más auto documentado y, por lo tanto, probablemente más legible.
Si está transfiriendo a través de una red (o incluso si no lo está), las columnas que no necesita son simplemente desperdicios.
fuente
*
a un conjunto de nombres).Especificación de la lista de columnas es generalmente la mejor opción, ya que su aplicación no se verá afectada si alguien añade inserciones / una columna de la tabla.
fuente
Especificar nombres de columna es definitivamente más rápido, para el servidor. Pero si
entonces es mejor que te quedes con SELECT *. En nuestro marco, el uso intensivo de SELECT * nos permite introducir un nuevo campo de contenido administrado en un sitio web en una tabla, dándole todos los beneficios del CMS (control de versiones, flujo de trabajo / aprobaciones, etc.), mientras solo toca el código en un par de puntos, en lugar de un par de docenas de puntos.
Sé que los gurús de DB me van a odiar por esto, adelante, voten por mí, pero en mi mundo, el tiempo de desarrollo es escaso y los ciclos de CPU son abundantes, por lo que ajusto en consecuencia lo que conservo y lo que desperdicio.
fuente
SELECT * es una mala práctica incluso si la consulta no se envía a través de una red.
Por supuesto, todo esto no importa mucho para un sistema pequeño y simple.
fuente
En cuanto al rendimiento, SELECT con columnas específicas puede ser más rápido (no es necesario leer todos los datos). Si su consulta realmente usa TODAS las columnas, SELECCIONAR con parámetros explícitos sigue siendo preferido. Cualquier diferencia de velocidad será básicamente imperceptible y casi de tiempo constante. Algún día su esquema cambiará, y este es un buen seguro para evitar problemas debido a esto.
fuente
Muchas buenas razones respondidas aquí hasta ahora, aquí hay otra que no se ha mencionado.
Nombrar explícitamente las columnas lo ayudará con el mantenimiento en el futuro. En algún momento vas a hacer cambios o solucionar problemas, y te encontrarás preguntando "dónde diablos se usa esa columna".
Si tiene los nombres listados explícitamente, entonces encontrar todas las referencias a esa columna, a través de todos sus procedimientos almacenados, vistas, etc., es simple. Simplemente descargue un script CREATE para su esquema de base de datos y busque texto en él.
fuente
Definitivamente definiendo las columnas, porque SQL Server no tendrá que hacer una búsqueda en las columnas para extraerlas. Si define las columnas, SQL puede omitir ese paso.
fuente
Siempre es mejor especificar las columnas que necesita, si lo piensa una vez, SQL no tiene que pensar "wtf is *" cada vez que realiza una consulta. Además de eso, alguien más tarde puede agregar columnas a la tabla que realmente no necesita en su consulta y estará mejor en ese caso al especificar todas sus columnas.
fuente
El problema con "select *" es la posibilidad de traer datos que realmente no necesita. Durante la consulta real de la base de datos, las columnas seleccionadas realmente no se agregan al cálculo. Lo que es realmente "pesado" es el transporte de datos de regreso a su cliente, y cualquier columna que realmente no necesite es simplemente desperdiciar el ancho de banda de la red y aumentar el tiempo que está esperando que regrese su consulta.
Incluso si utiliza todas las columnas traídas de un "select * ...", eso es solo por ahora. Si en el futuro cambia el diseño de la tabla / vista y agrega más columnas, comenzará a incluirlas en sus selecciones, incluso si no las necesita.
Otro punto en el que una declaración "select *" es mala es en la creación de la vista. Si crea una vista usando "select *" y luego agrega columnas a su tabla, la definición de la vista y los datos devueltos no coincidirán, y deberá volver a compilar sus vistas para que funcionen nuevamente.
Sé que escribir un "select *" es tentador, porque realmente no me gusta especificar manualmente todos los campos en mis consultas, pero cuando su sistema comience a evolucionar, verá que vale la pena pasar este tiempo extra / esfuerzo para especificar los campos en lugar de pasar mucho más tiempo y esfuerzo eliminando errores en sus vistas u optimizando su aplicación.
fuente
Si bien enumerar explícitamente las columnas es bueno para el rendimiento, no se vuelva loco.
Entonces, si usa todos los datos, intente SELECT * por simplicidad (imagine tener muchas columnas y hacer una consulta JOIN ... puede ser horrible). Entonces, mida. Compare con la consulta con los nombres de columna enumerados explícitamente.
No especules sobre el rendimiento, mídelo!
El listado explícito ayuda más cuando tiene una columna que contiene datos grandes (como el cuerpo de una publicación o artículo), y no la necesita en una consulta determinada. Luego, al no devolverlo en su servidor de respuesta DB puede ahorrar tiempo, ancho de banda y rendimiento de disco. El resultado de su consulta también será más pequeño, lo cual es bueno para cualquier caché de consultas.
fuente
Realmente debería seleccionar solo los campos que necesita, y solo el número requerido, es decir
Fuera de la base de datos, las consultas dinámicas corren el riesgo de ataques de inyección y datos mal formados. Por lo general, se soluciona esto mediante procedimientos almacenados o consultas parametrizadas. Además (aunque no es realmente un gran problema) el servidor tiene que generar un plan de ejecución cada vez que se ejecuta una consulta dinámica.
fuente
Seleccionar es igualmente eficiente (en términos de velocidad) si usa * o columnas.
La diferencia está en la memoria, no en la velocidad. Cuando selecciona varias columnas, SQL Server debe asignar espacio de memoria para atender la consulta, incluidos todos los datos de todas las columnas que ha solicitado, incluso si solo está utilizando una de ellas.
Lo que importa en términos de rendimiento es el plan de ejecución que a su vez depende en gran medida de su cláusula WHERE y el número de JOIN, OUTER JOIN, etc.
Para su pregunta simplemente use SELECT *. Si necesita todas las columnas, no hay diferencia de rendimiento.
fuente
NO es más rápido usar nombres de campo explícitos versus *, si y solo si, necesita obtener los datos para todos los campos.
El software de su cliente no debería depender del orden de los campos devueltos, por lo que también es una tontería.
Y es posible (aunque poco probable) que necesite obtener todos los campos usando * porque aún no sabe qué campos existen (piense en una estructura de base de datos muy dinámica).
Otra desventaja de usar nombres de campo explícitos es que si hay muchos de ellos y son largos, dificulta la lectura del código y / o el registro de consultas.
Entonces, la regla debería ser: si necesita todos los campos, use *, si solo necesita un subconjunto, asígneles un nombre explícito.
fuente
El resultado es demasiado grande. Es lento para generar y enviar el resultado del motor SQL al cliente.
El lado del cliente, al ser un entorno de programación genérico, no está ni debe estar diseñado para filtrar y procesar los resultados (por ejemplo, la cláusula WHERE, la cláusula ORDER), ya que el número de filas puede ser enorme (por ejemplo, decenas de millones de filas).
fuente
Nombrar cada columna que espera obtener en su aplicación también garantiza que su aplicación no se rompa si alguien modifica la tabla, siempre y cuando sus columnas sigan presentes (en cualquier orden).
fuente
Depende de la versión de su servidor de base de datos, pero las versiones modernas de SQL pueden almacenar en caché el plan de cualquier manera. Diría que vaya con lo que sea más fácil de mantener con su código de acceso a datos.
fuente
Una razón por la que es mejor explicar exactamente qué columnas desea es debido a posibles cambios futuros en la estructura de la tabla.
Si está leyendo datos manualmente utilizando un enfoque basado en índices para completar una estructura de datos con los resultados de su consulta, en el futuro, cuando agregue / elimine una columna, tendrá dolores de cabeza al tratar de descubrir qué salió mal.
En cuanto a lo que es más rápido, diferiré a otros por su experiencia.
fuente
Como con la mayoría de los problemas, depende de lo que quieras lograr. Si desea crear una cuadrícula db que permita todas las columnas en cualquier tabla, entonces "Seleccionar *" es la respuesta. Sin embargo, si solo necesita ciertas columnas y la adición o eliminación de columnas de la consulta se realiza con poca frecuencia, especifíquelas individualmente.
También depende de la cantidad de datos que desea transferir desde el servidor. Si una de las columnas se define como memo, gráfico, blob, etc. y no necesita esa columna, será mejor que no use "Seleccionar *" o obtendrá una gran cantidad de datos que no necesita. querer y tu rendimiento podría sufrir.
fuente
Para agregar a lo que todos los demás han dicho, si todas las columnas que está seleccionando están incluidas en un índice, su conjunto de resultados se extraerá del índice en lugar de buscar datos adicionales de SQL.
fuente
SELECT * es necesario si se desea obtener metadatos como el número de columnas.
fuente
Lo que todos dijeron arriba, más:
Si se esfuerza por obtener un código fácil de mantener, haga algo como:
SELECCIONE foo, barra DE widgets;
es legible al instante y muestra intención. Si hace esa llamada, sabe lo que está recibiendo. Si los widgets solo tienen columnas foo y bar, entonces seleccionar * significa que aún tiene que pensar en lo que va a recuperar, confirmar que el orden está asignado correctamente, etc. Sin embargo, si los widgets tienen más columnas pero solo le interesa foo y barra, luego su código se vuelve desordenado cuando consulta un comodín y luego solo usa parte de lo que se devuelve.
fuente
Y recuerde que si tiene una unión interna por definición, no necesita todas las columnas ya que los datos en las columnas de unión se repiten.
No es que enumerar columnas en el servidor SQl sea difícil o incluso lento. Simplemente arrástrelos desde el navegador de objetos (puede obtener todo de una vez arrastrando desde las columnas de palabras). Para poner un impacto permanente en el rendimiento de su sistema (porque esto puede reducir el uso de índices y el envío de datos innecesarios a través de la red es costoso) y hace que sea más probable que tenga problemas inesperados a medida que cambia la base de datos (a veces se agregan columnas que no desea que el usuario vea, por ejemplo) solo para ahorrar menos de un minuto de tiempo de desarrollo es miope y poco profesional.
fuente
En cuanto al rendimiento, he visto comentarios de que ambos son iguales. pero aspecto de usabilidad hay algunos + 'sy -'s
Cuando utiliza un (select *) en una consulta y si alguien modifica la tabla y agrega nuevos campos que no necesitan para la consulta anterior, es una sobrecarga innecesaria. ¿Y si el campo recién agregado es un blob o un campo de imagen? el tiempo de respuesta de tu consulta será muy lento entonces.
Por otro lado, si usa un (seleccione col1, col2, ..) y si la tabla se altera y agrega nuevos campos y si esos campos son necesarios en el conjunto de resultados, siempre necesita editar su consulta de selección después de la modificación de la tabla.
Pero sugiero siempre usar select col1, col2, ... en sus consultas y modificar la consulta si la tabla se altera más tarde ...
fuente
Definir absolutamente las columnas que desea SELECCIONAR siempre. No hay razón para no hacerlo y la mejora del rendimiento bien lo vale.
Nunca deberían haber dado la opción de "SELECCIONAR *"
fuente
Si necesita cada columna, simplemente use SELECT *, pero recuerde que el orden podría cambiar potencialmente, de modo que cuando consuma los resultados, acceda a ellos por nombre y no por índice.
Ignoraría los comentarios sobre cómo * necesita obtener la lista: es probable que analizar y validar columnas con nombre sea igual al tiempo de procesamiento, si no más. No optimices prematuramente ;-)
fuente
En términos de eficiencia de ejecución, no conozco ninguna diferencia significativa. Pero para la eficiencia de los programadores, escribiría los nombres de los campos porque
fuente
oye, sé práctico. use select * al crear prototipos y seleccione columnas específicas al implementar y desplegar. desde la perspectiva del plan de ejecución, ambos son relativamente idénticos en los sistemas modernos. sin embargo, la selección de columnas específicas limita la cantidad de datos que deben recuperarse del disco, almacenarse en la memoria y enviarse a través de la red.
en última instancia, el mejor plan es seleccionar columnas específicas.
fuente