Cambios de esquema
- Obtener por orden --- Si el código está buscando la columna # como la forma de obtener los datos, un cambio en el esquema hará que los números de columna se reajusten. Esto estropeará la aplicación y sucederán cosas malas.
- Recuperar por nombre --- Si el código está recuperando una columna por nombre, como
foo
, y otra tabla en la consulta agrega una columna foo
, la forma en que se maneja esto puede causar problemas al intentar obtener la columna correcta foo
.
De cualquier manera, un cambio de esquema puede causar problemas con la extracción de los datos.
Considere además si una columna que se estaba utilizando se elimina de la tabla. El select * from ...
sigue funcionando pero los errores a cabo al tratar de extraer los datos del conjunto de resultados. Si la columna se especifica en la consulta, la consulta generará un error en lugar de dar una clara indicación de qué y dónde está el problema.
Sobrecarga de datos
Algunas columnas pueden tener una cantidad significativa de datos asociada a ellas. Al volver a seleccionar, *
se extraerán todos los datos. Sí, esto es varchar(4096)
eso en 1000 filas que ha seleccionado de nuevo, lo que le proporciona 4 megabytes de datos adicionales posibles que no necesita, pero de todos modos se envía a través del cable.
En relación con el cambio de esquema, es posible que varchar no exista allí cuando creó la tabla por primera vez, pero ahora está allí.
Falta de transmitir intención
Cuando selecciona de nuevo *
y obtiene 20 columnas pero solo necesita 2 de ellas, no está transmitiendo la intención del código. Al mirar la consulta que se hace, select *
uno no sabe cuáles son las partes importantes de la misma. ¿Puedo cambiar la consulta para usar este otro plan en lugar de hacerlo más rápido al no incluir estas columnas? No lo sé porque la intención de lo que devuelve la consulta no está clara.
Veamos algunos violines SQL que exploran esos cambios de esquema un poco más.
Primero, la base de datos inicial: http://sqlfiddle.com/#!2/a67dd/1
DDL:
create table one (oneid int, data int, twoid int);
create table two (twoid int, other int);
insert into one values (1, 42, 2);
insert into two values (2, 43);
SQL:
select * from one join two on (one.twoid = two.twoid);
Y las columnas que vuelvas son oneid=1
, data=42
, twoid=2
, y other=43
.
Ahora, ¿qué sucede si agrego una columna a la tabla uno? http://sqlfiddle.com/#!2/cd0b0/1
alter table one add column other text;
update one set other = 'foo';
Y mis resultados de la misma consulta que antes son oneid=1
, data=42
, twoid=2
, y other=foo
.
Un cambio en una de las tablas altera los valores de a select *
y de repente su vinculación de 'otro' a un int arrojará un error y no sabe por qué.
Si en cambio su declaración SQL fue
select
one.oneid, one.data, two.twoid, two.other
from one join two on (one.twoid = two.twoid);
El cambio a la tabla uno no habría interrumpido sus datos. Esa consulta se ejecuta igual antes del cambio y después del cambio.
Indexación
Cuando haces un, select * from
estás tirando de todas las filas de todas las tablas que coinciden con las condiciones. Incluso mesas que realmente no te importan. Si bien esto significa que se transfieren más datos, hay otro problema de rendimiento que acecha más abajo en la pila.
Índices (relacionado con SO: ¿Cómo usar el índice en la instrucción select? )
Si está retirando muchas columnas, el optimizador del plan de la base de datos puede ignorar el uso de un índice porque de todos modos tendrá que recuperar todas esas columnas y tomará más tiempo usar el índice y luego recuperar todas las columnas en la consulta de lo que sería hacer un escaneo completo de la tabla.
Si solo está seleccionando, por ejemplo, el apellido de un usuario (que hace mucho y por lo tanto tiene un índice), la base de datos puede hacer un escaneo de solo índice (escaneo de índice wiki de postgres solo , escaneo de tabla completa de mysql vs completo) exploración de índice , exploración de solo índice: evitar el acceso a la tabla ).
Hay bastantes optimizaciones sobre la lectura solo de índices si es posible. La información se puede extraer más rápido en cada página de índice porque también está extrayendo menos; no está extrayendo todas esas otras columnas para el select *
. Es posible que un escaneo de solo índice arroje resultados del orden de 100 veces más rápido (fuente: Seleccionar * es incorrecto ).
Esto no quiere decir que una exploración de índice completa sea excelente, sigue siendo una exploración completa, pero es mejor que una exploración de tabla completa. Una vez que empiezas a perseguir todas las formas que select *
perjudican el rendimiento, sigues encontrando nuevas.
Lectura relacionada