Si solo necesito 2/3 columnas y hago una consulta en SELECT *
lugar de proporcionar esas columnas en la consulta de selección, ¿hay alguna degradación del rendimiento con respecto a más / menos E / S o memoria?
La sobrecarga de la red podría estar presente si selecciono * sin necesidad.
Pero en una operación de selección, ¿el motor de la base de datos siempre extrae tuplas atómicas del disco, o extrae solo las columnas solicitadas en la operación de selección?
Si siempre extrae una tupla, la sobrecarga de E / S es la misma.
Al mismo tiempo, puede haber un consumo de memoria para eliminar las columnas solicitadas de la tupla, si extrae una tupla.
Entonces, si ese es el caso, seleccione someColumn tendrá más sobrecarga de memoria que la de select *
fuente
SELECT
se ejecutan / procesen las consultas sea diferente de una base de datos a otra.CREATE VIEW foo_view AS SELECT * FROM foo;
, luego agregue columnas a la tabla foo más adelante, esas columnas no aparecerán automáticamente en foo_view como se esperaba. En otras palabras,*
en este contexto solo se expande una vez (en el momento de la creación de la vista), no según SELECT. Debido a las complicaciones derivadas de ALTER TABLE, diría que (en la práctica)*
se considera perjudicial.Respuestas:
Siempre saca una tupla (excepto en los casos en que la tabla ha sido segmentada verticalmente, dividida en columnas), por lo tanto, para responder a la pregunta que hizo, no importa desde una perspectiva de rendimiento. Sin embargo, por muchas otras razones, (debajo) siempre debe seleccionar específicamente las columnas que desee, por nombre.
Siempre extrae una tupla porque (en todos los RDBMS de los proveedores con los que estoy familiarizado), la estructura de almacenamiento en disco subyacente para todo (incluidos los datos de la tabla) se basa en páginas de E / S definidas (en SQL Server, por ejemplo, cada página está 8 kilobytes). Y cada lectura o escritura de E / S es por página. Es decir, cada escritura o lectura es una página completa de datos.
Debido a esta restricción estructural subyacente, una consecuencia es que cada fila de datos en una base de datos debe estar siempre en una sola página. No puede abarcar varias páginas de datos (excepto para cosas especiales como blobs, donde los datos de blob reales se almacenan en fragmentos de página separados, y la columna de fila de la tabla real solo obtiene un puntero ...). Pero estas excepciones son solo eso, excepciones, y generalmente no se aplican excepto en casos especiales (para tipos especiales de datos, o ciertas optimizaciones para circunstancias especiales)
Incluso en estos casos especiales, generalmente, la fila real de datos de la tabla en sí (que contiene el puntero a los datos reales para el Blob, o lo que sea), debe almacenarse en una sola página IO ...
EXCEPCIÓN. El único lugar donde
Select *
está bien, es en la subconsulta después de una cláusulaExists
oNot Exists
predicado, como en:EDITAR: Para abordar el comentario de @Mike Sherer, Sí, es cierto, tanto técnicamente, con un poco de definición para su caso especial, y estéticamente. Primero, incluso cuando el conjunto de columnas solicitadas es un subconjunto de las almacenadas en algún índice, el procesador de consultas debe buscar todas las columnas almacenadas en ese índice, no solo las solicitadas, por las mismas razones: TODAS las E / S deben realizarse en páginas, y los datos de índice se almacenan en páginas IO al igual que los datos de la tabla. Entonces, si define "tupla" para una página de índice como el conjunto de columnas almacenadas en el índice, la declaración sigue siendo cierta.
y la afirmación es verdadera desde el punto de vista estético porque el punto es que obtiene datos basados en lo que está almacenado en la página de E / S, no en lo que solicita, y esto es cierto si está accediendo a la página de E / S de la tabla base o a un índice Página de E / S.
Para otras razones para no usar
Select *
, vea ¿Por qué seSELECT *
considera dañino? :fuente
select *
, tendrá menos sobrecarga de memoria que laselect column
misma sobrecarga de E / S. entonces si dejamos la sobrecarga de la red.select *
si menos gastos generales que el deselect column
Hay varias razones por las que nunca (nunca) debes usar
SELECT *
en el código de producción:Como no le está dando a su base de datos ninguna pista sobre lo que desea, primero deberá verificar la definición de la tabla para determinar las columnas de esa tabla. Esa búsqueda costará algo de tiempo, no mucho en una sola consulta, pero se acumula con el tiempo
si solo necesita 2/3 de las columnas, está seleccionando 1/3 demasiados datos que deben recuperarse del disco y enviarse a través de la red
Si comienza a confiar en ciertos aspectos de los datos, por ejemplo, el orden de las columnas devueltas, podría obtener una desagradable sorpresa una vez que la tabla se reorganice y se agreguen nuevas columnas (o se eliminen las existentes)
en SQL Server (no estoy seguro acerca de otras bases de datos), si necesita un subconjunto de columnas, siempre existe la posibilidad de que un índice no agrupado cubra esa solicitud (contenga todas las columnas necesarias). Con un
SELECT *
, estás renunciando a esa posibilidad desde el primer momento. En este caso particular, los datos se recuperarían de las páginas de índice (si contienen todas las columnas necesarias) y, por lo tanto, la E / S de disco y la sobrecarga de memoria serían mucho menores en comparación con hacer unaSELECT *....
consulta.Sí, inicialmente se necesita un poco más de escritura (herramientas como SQL Prompt para SQL Server incluso lo ayudarán allí), pero este es realmente un caso en el que hay una regla sin excepción: nunca use SELECT * en su código de producción. NUNCA.
fuente
Where Exists (Select * From ...
) el uso deSelect *
ciertamente no es un problema, y en algunos círculos se considera una mejor práctica.IF EXISTS(SELECT *...
es un caso especial, ya que allí no se recuperan datos, pero es solo una verificación de existencia, el SELECT * no es un problema allí ...Usted debe siempre solamente
select
las columnas que en realidad se necesita. Nunca es menos eficiente seleccionar menos en lugar de más, y también se topa con menos efectos secundarios inesperados, como acceder a las columnas de resultados en el lado del cliente por índice, luego hacer que esos índices se vuelvan incorrectos al agregar una nueva columna a la tabla.[editar]: significaba acceder. Estúpido cerebro aún despertando.
fuente
SELECT *
con él.A menos que esté almacenando grandes blobs, el rendimiento no es una preocupación. La gran razón para no usar SELECT * es que si usa filas devueltas como tuplas, las columnas vuelven en el orden que especifique el esquema, y si eso cambia, tendrá que arreglar todo su código.
Por otro lado, si usa acceso de estilo diccionario, no importa en qué orden vuelvan las columnas porque siempre está accediendo a ellas por nombre.
fuente
Esto inmediatamente me hace pensar en una tabla que estaba usando que contenía una columna de tipo
blob
; generalmente contenía una imagen JPEG, de unos pocosMb
s de tamaño.No hace falta decir que no hice
SELECT
esa columna a menos que realmente la necesitara. Tener esos datos flotando, especialmente cuando seleccioné varias filas, fue una molestia.Sin embargo, admitiré que, de lo contrario, suelo consultar todas las columnas de una tabla.
fuente
Durante una selección de SQL, la base de datos siempre se referirá a los metadatos de la tabla, independientemente de si es SELECT * para SELECT a, b, c ... ¿Por qué? Porque ahí es donde está la información sobre la estructura y el diseño de la tabla en el sistema.
Tiene que leer esta información por dos razones. Uno, simplemente compilar la declaración. Debe asegurarse de especificar al menos una tabla existente. Además, la estructura de la base de datos puede haber cambiado desde la última vez que se ejecutó una declaración.
Ahora, obviamente, los metadatos de la base de datos se almacenan en caché en el sistema, pero aún es necesario procesarlo.
A continuación, los metadatos se utilizan para generar el plan de consulta. Esto sucede cada vez que se compila una declaración también. Nuevamente, esto se ejecuta contra metadatos almacenados en caché, pero siempre se hace.
El único momento en que este procesamiento no se realiza es cuando la base de datos está utilizando una consulta precompilada o ha almacenado en caché una consulta anterior. Este es el argumento para usar parámetros de enlace en lugar de SQL literal. "SELECT * FROM TABLE WHERE key = 1" es una consulta diferente a "SELECT * FROM TABLE WHERE key =?" y el "1" está vinculado a la llamada.
Las bases de datos dependen en gran medida del almacenamiento en caché de páginas para su trabajo. Muchos DB modernos son lo suficientemente pequeños como para caber completamente en la memoria (o, tal vez debería decir, la memoria moderna es lo suficientemente grande como para caber muchos DB). Luego, su costo de E / S principal en el back-end es el inicio de sesión y el vaciado de páginas.
Sin embargo, si todavía está presionando el disco para su base de datos, una optimización principal realizada por muchos sistemas es confiar en los datos en los índices, en lugar de las tablas en sí.
Si usted tiene:
Entonces, si hace "SELECT id, name FROM customer WHERE id = 1", es muy probable que DB extraiga estos datos del índice, en lugar de las tablas.
¿Por qué? Es probable que use el índice de todos modos para satisfacer la consulta (frente a un escaneo de tabla), y aunque 'nombre' no se usa en la cláusula where, ese índice seguirá siendo la mejor opción para la consulta.
Ahora la base de datos tiene todos los datos que necesita para satisfacer la consulta, por lo que no hay razón para ir a las páginas de la tabla. El uso del índice da como resultado menos tráfico de disco ya que tiene una mayor densidad de filas en el índice en comparación con la tabla en general.
Esta es una explicación manual de una técnica de optimización específica utilizada por algunas bases de datos. Muchos tienen varias técnicas de optimización y ajuste.
Al final, SELECT * es útil para consultas dinámicas que tiene que escribir a mano, nunca lo usaría para "código real". La identificación de columnas individuales le da al DB más información que puede usar para optimizar la consulta, y le brinda un mejor control en su código contra cambios de esquema, etc.
fuente
Creo que no hay una respuesta exacta para su pregunta, porque tiene un rendimiento reflexivo y la facilidad de mantener sus aplicaciones.
Select column
es más funcionalselect *
, pero si está desarrollando un sistema de objetos orientado, le gustará usarloobject.properties
y puede necesitar propiedades en cualquier parte de las aplicaciones, entonces necesitará escribir más métodos para obtener propiedades en situaciones especiales si no lo hace useselect *
y complete todas las propiedades. Sus aplicaciones deben tener un buen rendimiento utilizandoselect *
y, en algunos casos, necesitará utilizar la columna de selección para mejorar el rendimiento. Entonces tendrá lo mejor de dos mundos, facilidad para escribir y mantener aplicaciones y rendimiento cuando lo necesite.fuente
La respuesta aceptada aquí es incorrecta. Me encontré con esto cuando otra pregunta se cerró como un duplicado de esto (mientras todavía estaba escribiendo mi respuesta, grr, por lo tanto, el siguiente SQL hace referencia a la otra pregunta).
Siempre debe usar SELECT atributo, atributo ... NO SELECCIONAR *
Es principalmente por problemas de rendimiento.
No es un ejemplo muy útil. Considere en su lugar:
Si hay un índice en (nombre, teléfono), entonces la consulta se puede resolver sin tener que buscar los valores relevantes de la tabla; hay un índice de cobertura .
Además, suponga que la tabla tiene un BLOB que contiene una imagen del usuario, y un CV cargado, y una hoja de cálculo ... usando SELECT * extraerá toda esta información en los buffers DBMS (forzando otra información útil de la caché). Luego, todo se enviará al cliente utilizando el tiempo de actividad en la red y la memoria en el cliente para datos que son redundantes.
También puede causar problemas funcionales si el cliente recupera los datos como una matriz enumerada (como mysql_fetch_array de PHP ($ x, MYSQL_NUM)). Tal vez cuando el código fue escrito 'teléfono' fue la tercera columna devuelta por SELECT *, pero luego aparece alguien y decide agregar una dirección de correo electrónico a la mesa, colocada antes de 'teléfono'. El campo deseado ahora se desplaza a la cuarta columna.
fuente
Hay razones para hacer las cosas de cualquier manera. Uso mucho SELECT * en PostgreSQL porque hay muchas cosas que puedes hacer con SELECT * en PostgreSQL que no puedes hacer con una lista explícita de columnas, particularmente cuando estás en procedimientos almacenados. De manera similar, en Informix, SELECT * sobre un árbol de tablas heredado puede proporcionar filas irregulares, mientras que una lista de columnas explícita no puede porque también se devuelven columnas adicionales en las tablas secundarias.
La razón principal por la que hago esto en PostgreSQL es que garantiza que obtenga un tipo bien formado específico para una tabla. Esto me permite tomar los resultados y usarlos como el tipo de tabla en PostgreSQL. Esto también permite muchas más opciones en la consulta que una lista de columnas rígidas.
Por otro lado, una lista de columnas rígidas le brinda una verificación a nivel de aplicación de que los esquemas db no han cambiado de cierta manera y esto puede ser útil. (Hago tales controles en otro nivel).
En cuanto al rendimiento, tiendo a usar VIEW y procedimientos almacenados que devuelven tipos (y luego una lista de columnas dentro del procedimiento almacenado). Esto me da control sobre qué tipos se devuelven.
Pero tenga en cuenta que estoy usando SELECT * generalmente contra una capa de abstracción en lugar de tablas base.
fuente
Referencia tomada de este artículo:
Sin SELECT *: cuando utiliza "SELECT *" en ese momento, está seleccionando más columnas de la base de datos y es posible que su aplicación no utilice parte de esta columna. Esto creará un costo y carga adicionales en el sistema de base de datos y más viajes de datos a través de la red.
Con SELECT *: si tiene requisitos especiales y creó un entorno dinámico cuando la columna de agregar o eliminar se maneja automáticamente por código de aplicación. En este caso especial, no necesita cambiar el código de la aplicación y la base de datos y esto afectará automáticamente el entorno de producción. En este caso puede usar "SELECCIONAR *".
fuente
Solo para agregar un matiz a la discusión que no veo aquí: en términos de E / S, si está utilizando una base de datos con almacenamiento orientado a columnas puede hacer MUCHO menos E / S si solo consulta ciertas columnas A medida que avanzamos hacia los SSD, los beneficios pueden ser un poco más pequeños en comparación con el almacenamiento orientado a filas, pero hay a) solo leer los bloques que contienen columnas que le interesan b) compresión, que generalmente reduce en gran medida el tamaño de los datos en el disco y, por lo tanto, el volumen de datos leídos del disco.
Si no está familiarizado con el almacenamiento orientado a columnas, una implementación para Postgres proviene de Citus Data, otra es Greenplum, otra Paraccel, otra (en términos generales) es Amazon Redshift. Para MySQL está Infobright, el InfiniDB ahora casi desaparecido. Otras ofertas comerciales incluyen Vertica de HP, Sybase IQ, Teradata ...
fuente
igual
fuente