La esencia de la cita de no optimizar prematuramente es buscar un código simple y directo y luego usar un generador de perfiles para señalar los puntos calientes, que luego puede optimizar para ser eficiente.
Cuando usa select *, hace que sea imposible crear un perfil, por lo tanto, no está escribiendo un código claro y directo y va en contra del espíritu de la cita. select *
Es un antipatrón.
Por lo tanto, seleccionar columnas no es una optimización prematura. Algunas cosas fuera de mi cabeza ...
- Si especifica columnas en una instrucción SQL, el motor de ejecución de SQL producirá un error si esa columna se elimina de la tabla y se ejecuta la consulta.
- Puede escanear más fácilmente el código donde se usa esa columna.
- Siempre debe escribir consultas para recuperar la menor cantidad de información.
- Como otros mencionan, si usa el acceso a la columna ordinal, nunca debe usar select *
- Si su declaración SQL une tablas, select * le da todas las columnas de todas las tablas en la combinación
El corolario es que usando select *
...
- Las columnas utilizadas por la aplicación son opacas.
- Los DBA y sus analizadores de consultas no pueden ayudar al bajo rendimiento de su aplicación
- El código es más frágil cuando se producen cambios.
- Su base de datos y red están sufriendo porque están trayendo demasiados datos (E / S)
- Las optimizaciones del motor de base de datos son mínimas ya que recupera todos los datos independientemente (lógico).
Escribir un SQL correcto es tan fácil como escribir Select *
. Entonces, la persona perezosa real escribe el SQL apropiado porque no quiere volver a visitar el código e intenta recordar lo que estaba haciendo cuando lo hizo. No quieren explicar a los DBA sobre cada fragmento de código. No quieren explicar a sus clientes por qué la aplicación se ejecuta como un perro.
Si su código depende de que las columnas estén en un orden específico, su código se romperá cuando haya cambios en la tabla. Además, puede estar obteniendo demasiado de la tabla cuando selecciona *, especialmente si hay un campo binario en la tabla.
El hecho de que esté utilizando todas las columnas ahora, no significa que alguien más no va a agregar una columna adicional a la tabla.
También agrega sobrecarga al almacenamiento en caché de ejecución del plan, ya que tiene que recuperar los metadatos sobre la tabla para saber qué columnas están en *.
fuente
Una razón importante es que si alguna vez agrega / elimina columnas de su tabla, cualquier consulta / procedimiento que realice una llamada SELECT * ahora obtendrá más o menos columnas de datos de lo esperado.
fuente
De manera indirecta, está rompiendo la regla de modularidad sobre el uso de mecanografía estricta siempre que sea posible. Explícito es casi universalmente mejor.
Incluso si ahora necesita cada columna de la tabla, se podrían agregar más más adelante, que se desplegarán cada vez que ejecute la consulta y podrían afectar el rendimiento. Daña el rendimiento porque
Cuando TO usar seleccione *
Cuando NECESITA explícitamente cada columna de la tabla, en lugar de necesitar cada columna de la tabla QUE EXISTÍA EN EL MOMENTO EN QUE ESCRIBIÓ LA CONSULTA. Por ejemplo, si estuviera escribiendo una aplicación de administración de DB que necesitara mostrar todo el contenido de la tabla (lo que sea que sea) podría usar ese enfoque.
fuente
SELECT *
sería cuando esté haciendo consultas de prueba con el cliente db.Hay unas pocas razones:
Nota: Elegí INTEGER en el ejemplo anterior porque tienen un tamaño fijo de 4 bytes.
fuente
Si su aplicación obtiene datos con SELECT * y se cambia la estructura de la tabla en la base de datos (digamos que se elimina una columna), su aplicación fallará en cada lugar que haga referencia al campo faltante. Si en su lugar incluye todas las columnas en su consulta, su aplicación se dividirá en el (con suerte) un lugar donde inicialmente obtiene los datos, facilitando la solución.
Dicho esto, hay una serie de situaciones en las que SELECT * es deseable. Una es una situación que encuentro todo el tiempo, donde necesito replicar una tabla completa en otra base de datos (como SQL Server a DB2, por ejemplo). Otra es una aplicación escrita para mostrar tablas genéricamente (es decir, sin ningún conocimiento de ninguna tabla en particular).
fuente
De hecho, noté un comportamiento extraño cuando lo usé
select *
en vistas en SQL Server 2005.Ejecute la siguiente consulta y verá lo que quiero decir.
Compare los resultados de las últimas 2 declaraciones de selección. Creo que lo que verá es el resultado de Seleccionar * haciendo referencia a columnas por índice en lugar de nombre.
Si reconstruye la vista, volverá a funcionar bien.
EDITAR
He agregado una pregunta separada, * "seleccionar * de la tabla" frente a "seleccionar colA, colB, etc. de la tabla" comportamiento interesante en SQL Server 2005 * para analizar ese comportamiento con más detalles.
fuente
Puede unir dos tablas y usar la columna A de la segunda tabla. Si luego agrega la columna A a la primera tabla (con el mismo nombre pero posiblemente con un significado diferente), lo más probable es que obtenga los valores de la primera tabla y no de la segunda como antes. Eso no sucederá si especifica explícitamente las columnas que desea seleccionar.
Por supuesto, especificar las columnas también a veces causa errores si olvida agregar las nuevas columnas a cada cláusula select. Si no se necesita la nueva columna cada vez que se ejecuta la consulta, puede pasar algún tiempo antes de que se note el error.
fuente
Entiendo a dónde vas con respecto a la optimización prematura, pero eso realmente solo llega a un punto. La intención es evitar una optimización innecesaria al principio. ¿Sus tablas no están indexadas? ¿Usaría nvarchar (4000) para almacenar un código postal?
Como otros han señalado, hay otros aspectos positivos para especificar cada columna que pretende utilizar en la consulta (como la capacidad de mantenimiento).
fuente
Cuando estás especificando columnas, también te estás atando a un conjunto específico de columnas y haciéndote menos flexible, haciendo que Feuerstein ruede, bueno, donde sea que esté. Solo un pensamiento.
fuente
SELECCIONAR * no siempre es malo. En mi opinión al menos. Lo uso con bastante frecuencia para consultas dinámicas que devuelven una tabla completa, más algunos campos calculados.
Por ejemplo, quiero calcular geometrías geográficas a partir de una tabla "normal", que es una tabla sin ningún campo de geometría, pero con campos que contienen coordenadas. Yo uso postgresql, y su extensión espacial postgis. Pero el principio se aplica a muchos otros casos.
Un ejemplo:
una tabla de lugares, con coordenadas almacenadas en campos etiquetados x, y, z:
CREATE TABLE lugares (place_id entero, x numeric (10, 3), y numeric (10, 3), z numeric (10, 3), descripción varchar);
vamos a alimentarlo con algunos valores de ejemplo:
INSERTAR EN lugares (place_id, x, y, z, descripción) VALORES
(1, 2.295, 48.863, 64, 'Paris, Place de l \' Étoile '),
(2, 2.945, 48.858, 40,' Paris, Tour Eiffel '),
(3, 0.373, 43.958, 90,' Condón, Cathédrale St-Pierre ');
Quiero poder asignar el contenido de esta tabla, utilizando algún cliente SIG. La forma normal es agregar un campo de geometría a la tabla y construir la geometría, en función de las coordenadas. Pero preferiría obtener una consulta dinámica: de esta manera, cuando cambio las coordenadas (correcciones, más precisión, etc.), los objetos mapeados realmente se mueven, dinámicamente. Así que aquí está la consulta con SELECT * :
CREAR O REEMPLAZAR VISUALIZAR lugares_puntos COMO
SELECCIONAR *,
GeomFromewkt ('SRID = 4326; POINT (' || x || '' || y || '' || z || ')')
DESDE lugares;
Consulte postgis, para el uso de la función GeomFromewkt ().
Aquí está el resultado:
SELECCIONAR * DESDE lugares_puntos;
La columna de la derecha ahora puede ser utilizada por cualquier programa SIG para mapear adecuadamente los puntos.
Desearía que la definición de la VISTA pudiera mantenerse "tal cual", con el *, pero hélas no es el caso: así es como postgresql la almacena internamente:
SELECCIONA places.place_id, places.x, places.y, places.z, places.description, geomfromewkt ((((((('SRID = 4326; POINT (' :: text || places.x) || '': : texto) || lugares.y) || '' :: texto) || lugares.z) || ')' :: texto) AS geomfromewkt FROM lugares;
fuente
Incluso si usa todas las columnas pero aborda la matriz de filas por índice numérico, tendrá problemas si agrega otra fila más adelante.
¡Entonces, básicamente, es una cuestión de mantenibilidad! Si no utiliza el selector *, no tendrá que preocuparse por sus consultas.
fuente
Si selecciona solo las columnas que necesita, el conjunto de datos en la memoria será más pequeño y, por lo tanto, su aplicación se acelerará.
Además, muchas herramientas (por ejemplo, procedimientos almacenados) también almacenan planes de ejecución de consultas en caché. Si luego agrega o elimina una columna (particularmente fácil si está seleccionando una vista), la herramienta a menudo fallará cuando no recupere los resultados que espera.
fuente
Hace que su código sea más ambiguo y más difícil de mantener; porque está agregando datos adicionales no utilizados al dominio, y no está claro cuál fue su intención y cuál no. (También sugiere que es posible que no lo sepa o que no le importe).
fuente
Para responder su pregunta directamente: No utilice "SELECCIONAR *" cuando haga que su código sea más flexible para los cambios en las tablas subyacentes. Su código debe romperse solo cuando se realiza un cambio en la tabla que afecta directamente los requisitos de su programa.
Su aplicación debe aprovechar la capa de abstracción que proporciona el acceso relacional.
fuente
No uso SELECT * simplemente porque es agradable ver y saber qué campos estoy recuperando.
fuente
En general, es malo usar 'select *' dentro de las vistas porque se verá obligado a recompilar la vista en caso de un cambio en la columna de la tabla. Al cambiar las columnas de la tabla subyacente de una vista, obtendrá un error para las columnas no existentes hasta que regrese y vuelva a compilar.
fuente
Está bien cuando lo estás haciendo,
exists(select * ...)
ya que nunca se expande. De lo contrario, solo es útil al explorar tablas con declaraciones de selección temporales o si tenía un CTE definido anteriormente y desea cada columna sin volver a escribirlas todas.fuente
Solo para agregar una cosa que nadie más ha mencionado.
Select *
devuelve todas las columnas, alguien puede agregar una columna más tarde que no necesariamente desea que los usuarios puedan ver, como quién actualizó por última vez los datos o una marca de tiempo o notas que solo los gerentes deberían ver no todos los usuarios, etc.Además, al agregar una columna, el impacto en el código existente debe revisarse y considerarse para ver si se necesitan cambios en función de la información almacenada en la columna. Al usar
select *
, esa revisión a menudo se omitirá porque el desarrollador asumirá que nada se romperá. Y, de hecho, nada puede parecer explícitamente roto, pero las consultas ahora pueden comenzar a devolver algo incorrecto. El hecho de que nada se rompa explícitamente no significa que no debería haber habido cambios en las consultas.fuente
porque "select *" desperdiciará memoria cuando no necesite todos los campos. Pero para el servidor sql, su rendimiento es el mismo.
fuente