Modifiche allo schema
- Recupera per ordine --- Se il codice sta recuperando la colonna # come modo per ottenere i dati, una modifica dello schema comporterà la regolazione dei numeri di colonna. Ciò incasinerà l'applicazione e accadranno cose brutte.
- Recupera per nome --- Se il codice sta recuperando una colonna per nome come
foo
, e un'altra tabella nella query aggiunge una colonna foo
, il modo in cui questa viene gestita può causare problemi quando si cerca di ottenere la colonna giusta foo
.
In entrambi i casi, una modifica dello schema può causare problemi con l'estrazione dei dati.
Inoltre, considerare se una colonna in uso viene rimossa dalla tabella. Il select * from ...
funziona ancora, ma gli errori fuori quando si cerca di estrarre i dati dal set di risultati. Se la colonna è specificata nella query, la query si spegnerà invece fornendo un'indicazione chiara su cosa e dove si trova il problema.
Sovraccarico di dati
Alcune colonne possono avere una quantità significativa di dati associati ad essi. Selezionando indietro *
verranno estratti tutti i dati. Sì, ecco che è varchar(4096)
su 1000 righe che hai selezionato indietro dandoti altri 4 megabyte di dati che non ti servono, ma vengono comunque inviati attraverso il filo.
In relazione alla modifica dello schema, quel varchar potrebbe non esistere lì quando hai creato la tabella per la prima volta, ma ora è lì.
Mancata trasmissione dell'intento
Quando selezioni indietro *
e ottieni 20 colonne ma ne hai bisogno solo 2, non stai comunicando l'intento del codice. Quando si guarda la query che fa select *
uno non si sa quali sono le parti importanti di esso. Posso modificare la query per utilizzare questo altro piano invece di renderlo più veloce non includendo queste colonne? Non lo so perché l'intento di ciò che la query restituisce non è chiaro.
Vediamo alcuni violini SQL che esplorano un po 'di più quelle modifiche allo schema .
Innanzitutto, il database iniziale: 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);
E le colonne che si ottiene indietro sono oneid=1
, data=42
, twoid=2
, e other=43
.
Ora, cosa succede se aggiungo una colonna alla tabella uno? http://sqlfiddle.com/#!2/cd0b0/1
alter table one add column other text;
update one set other = 'foo';
E i miei risultati dalla stessa query di prima sono oneid=1
, data=42
, twoid=2
, e other=foo
.
Un cambiamento in una delle tabelle interrompe i valori di a select *
e all'improvviso il tuo legame di "altro" con un int genererà un errore e non sai perché.
Se invece fosse la tua istruzione SQL
select
one.oneid, one.data, two.twoid, two.other
from one join two on (one.twoid = two.twoid);
La modifica alla tabella uno non avrebbe interrotto i tuoi dati. Quella query viene eseguita allo stesso modo prima della modifica e dopo la modifica.
indicizzazione
Quando lo fai, select * from
stai tirando tutte le righe da tutte le tabelle che soddisfano le condizioni. Anche i tavoli di cui non ti importa davvero. Mentre questo significa che vengono trasferiti più dati, c'è un altro problema di prestazioni in agguato nello stack.
Indici. (correlato a SO: come utilizzare l'indice nell'istruzione select? )
Se si stanno ritirando molte colonne, l'ottimizzatore del piano di database potrebbe ignorare l'utilizzo di un indice poiché sarà comunque necessario recuperare tutte quelle colonne e occorrerebbe più tempo per utilizzare l'indice e quindi recuperare tutte le colonne nella query di quello sarebbe solo fare una scansione completa della tabella.
Se stai solo selezionando il, per esempio, il cognome di un utente (che fai molto e quindi hai un indice su di esso), il database può fare solo una scansione dell'indice ( scansione solo dell'indice wiki postgres , scansione della tabella completa mysql vs full scansione indice , scansione solo indice: evitare l'accesso alla tabella ).
Esistono parecchie ottimizzazioni sulla lettura solo dagli indici, se possibile. Le informazioni possono essere estratte più rapidamente su ogni pagina dell'indice perché ne stai estraendo anche di meno - non stai inserendo tutte quelle altre colonne per il select *
. È possibile che solo una scansione dell'indice restituisca risultati dell'ordine di 100 volte più veloce (fonte: selezionare * è errato ).
Ciò non significa che una scansione completa dell'indice sia eccezionale, è comunque una scansione completa, ma è meglio di una scansione completa della tabella. Una volta che inizi a inseguire tutti i modi in cui ciò select *
danneggia la performance, continui a trovarne di nuovi.
Lettura correlata