2009-05-12 13 views
6

Se ho due queryIl numero di colonne restituite influisce sulla velocità di una query?

SELECT Id, Forename, Surname 
FROM Person 
WHERE PersonName Like(‘%frank%’) 

E

SELECT * 
FROM Person 
WHERE PersonName Like(‘%frank%’) 

Quale interrogazione saranno più veloci? La clausola where/table unisce il fattore più grande o il numero di colonne restituite?

Sto chiedendo perché sto costruendo una serie di oggetti che si associano alle tabelle del database. In genere ogni oggetto avrà almeno questi tre metodi:

Select - Seleziona tutto

List - Seleziona abbastanza che è può essere usato per compilare un elenco a discesa

Search - Consente di selezionare tutto ciò che è visibile nell'immagine risultati, in genere circa 6 colonne.

Se ogni query ha restituito esattamente lo stesso insieme di colonne, la manutenzione e il test del codice dovrebbero essere più banali. È improbabile che il database superi le 50.000 righe in una data tabella, quindi se la differenza nelle prestazioni è ridotta, prenderò il risparmio nei tempi di sviluppo. Se la performance sta per cadere nel pavimento, allora lavorerò da una diversa angolazione.

Quindi, per facilità di sviluppo, è ragionevole SELECT * o è ingenuo?

+3

Solo una piccola grammatica: * influenza * la velocità di una query. –

+0

http://xkcd.com/326/ – Quassnoi

+0

La politica estera può influire su qualcosa, ma un numero di colonne non può – Andomar

risposta

23

È meglio evitare SELECT *

  • Essa conduce alla confusione quando si modifica il layout della tabella.
  • Seleziona colonne non necessarie e i pacchetti di dati diventano più grandi.
  • Le colonne possono avere nomi duplicati, che è anche non va bene per alcune applicazioni
  • Se tutte le colonne necessari sono coperti da un indice, SELECT columns useranno solo questo indice, mentre SELECT * necessario visitare i record della tabella a ottieni i valori che non ti servono. Anche male per le prestazioni.
+0

Sono d'accordo con la maggior parte dei tuoi punti ma "Le colonne possono ottenere nomi duplicati" - questa è una novità per me. Come mai? – paxdiablo

+2

@Pax: se si ha un self-join all'interno della query o si uniscono due tabelle che hanno alcune colonne con lo stesso nome. – Quassnoi

+0

@Pax Seleziona * Da Persona p, Contatto c Dove c.PersonID = p.PersonID; questo normalmente avrà [Nome] nelle 2 tabelle, ad esempio – balexandre

-2

Sicuro. Meglio nominare le colonne che vuoi recuperare.

0

Se la persona ha solo Id, Nome e Cognome, le query dovrebbero essere equivalenti. Tuttavia, il tempo di query aumenterà proporzionalmente al numero di colonne (quantità effettiva di dati) restituiti.

Inoltre, se la query richiede solo quelle tre colonne, è necessario chiedere solo quelle tre. Se SELEZIONA * e cambi lo schema in un secondo momento, in pratica stai semplicemente aggiungendo un'ulteriore elaborazione a tutte le tue query con un reale vantaggio aggiunto.

0

Vorrei visitare questo question sul perché utilizzare il costrutto "Seleziona *" non è preferito.

Nella mia esperienza, la selezione di 3 colonne rispetto a selezione * in una tabella a 3 colonne potrebbe non avere un notevole impatto sulle prestazioni, ma man mano che le tabelle diventano più grandi, noterete una differenza di prestazioni.

0

In generale, in qualsiasi situazione, si vuole stare lontano da utilizzando

SELECT * FROM TABLE 

nel codice. Ciò potrebbe portare a diversi problemi, uno solo dei quali è la prestazione. Altri due che mi vengono in mente sono l'utilizzo delle risorse (se selezioni colonne che non ti servono, o qualcuno aggiunge colonne in un secondo momento ... stai riportando dati e sprechi di memoria) e leggibilità del codice (se qualcuno vede SELECT * FROM nel tuo codice ... non necessariamente sapranno quali colonne sono effettivamente utilizzate nella tua applicazione).

Solo un paio di cose a cui pensare ... ma la cosa migliore è NON usarlo.

0

Sì, sì. Fondamentalmente:

  • Più i dati devono essere trasferiti dal server di database del server
  • Il database deve recuperare più dati

Non si deve usare select *

0

Oltre al altre risposte, considera che SELECT * restituirà i dati da tutte le tabelle della query. Inizia ad aggiungere altre tabelle tramite JOIN e inizierai a vedere cose che non vuoi vedere.

Credo di aver visto anche casi in cui SELECT * richiede che i dati vengano effettivamente recuperati da una tabella unita, anziché utilizzare solo gli indici su quella tabella per limitare il set di risultati complessivo. Non riesco a pensare ad un esempio di quello, però.

1

Se si ricorda correttamente dal college (ed è stato un po '), selezionare * non è preferibile, ma non così male - fino a quando non si inizia a partecipare. Quando si entra nell'algebra relazionale della creazione delle tuple unite, ogni colonna si aggiunge al tempo, quindi eviterei definitivamente se possibile.

6

SELECT * di solito non è mai una buona idea. Potrebbe non rallentare molto il recupero del DBMS, ma probabilmente porterà a un numero maggiore di dati trasmessi sulla rete rispetto al necessario.

Tuttavia, è probabile che questo rimanga insignificante utilizzando la clausola LIKE '%frank%' che è fondamentalmente non indicizzabile e comporterà una scansione completa della tabella.

Si consiglia di prendere in considerazione la possibilità di ripulire i dati non appena entra nel database, poiché quasi certamente le query successive verranno eseguite molto più velocemente.

Se siete alla ricerca di Frank, quindi assicurarsi che sia memorizzato come Frank ed impiego:

select x,y,z from table where name = 'frank' 

Se si desidera ottenere franklin così, l'uso:

select x,y,z from table where name like 'frank%' 

Entrambi questi saranno essere in grado di utilizzare un indice sulla colonna nome, non lo sarà il "%frank%".

0

Ci sono più dimensioni a questo. Per una volta il * renderà il tuo codice più fragile. Quando nelle versioni successive si modifica il codice di layout delle tabelle che si basa sull'ordine delle colonne potrebbe interrompersi, oppure non è possibile leggere o modificare le colonne sbagliate se i tipi di dati corrispondono ancora a quelli che possono essere un problema davvero sgradevole!

Inoltre, se si richiedono sempre tutte le colonne, sarà necessario più memoria sul client del database e sul server del database per le colonne non necessarie. Questo può essere molto costoso se la tabella contiene campi di caratteri lunghi, molti campi e/o BLOB. Selezionando le colonne non necessarie si sfrutterà anche la cache del server invadendo il contenuto superfluo che non viene mai visto da un client.

Quindi in generale non si dovrebbe usare. La maggior parte degli strumenti di mappatura relazionale degli oggetti genera SQL che contiene comunque tutti i nomi delle colonne, quindi durante lo sviluppo questo probabilmente non è comunque un problema. Io personalmente tendo ad usare * solo per query ad hoc veloci che devo digitare manualmente.

1

Il numero di colonne nella tabella non influisce sul rendimento della query. Sarà il numero di colonne utilizzate nella query.

Nota seguente esempio dal manuale concetti Oracle:

Row formato e le dimensioni Oracle memorizza ogni riga di una tabella database contenente dati per meno di 256 colonne come uno o più pezzi di riga. Se un'intera riga può essere inserita in un singolo blocco , Oracle memorizza la riga come un pezzo di riga. Tuttavia, se tutti i dati di una riga non può essere inserito in un blocco di dati singolo o se un aggiornamento di una riga esistente provoca la riga outgrow suo blocco di dati, quindi Oracle memorizza la riga utilizzando fila multipla pezzi. Un blocco dati contiene in genere un solo pezzo di riga per ogni riga. Quando Oracle deve memorizzare una riga in più di un pezzo di riga, è concatenato su più blocchi .

Quando una tabella contiene più di 255 colonne, righe che contengono dati dopo la colonna 255 ° sono suscettibili di essere incatenato nello stesso blocco. Questo è chiamato concatenamento intra-blocco. I pezzi di una fila concatenata vengono concatenati usando le pedine dei pezzi. Con il concatenamento intra-blocco , gli utenti ricevono tutti i dati nello stesso blocco. Se la riga si adatta al blocco , gli utenti non vedono un effetto in prestazioni I/O, poiché non è richiesta alcuna operazione di I/O supplementare per recuperare il resto della riga .

TUTTAVIA: Se ci sono 400 colonne, ho pronto a scommettere che la maggior parte dei file non si adatta in un blocco e, quindi, si vedrà un molto piu 'sequenziale di file db leggere' che normalmente richiesto. Inoltre, I ricordo che Steve Adams (o qualcuno molto tempo fa) menziona che c'è un costo aggiuntivo per accedere a una colonna "più in basso nella lista" - mi dispiace non avere quel link.

+0

Questo vale anche per MS Sql? – ilivewithian

2

Indipendentemente dai problemi di prestazioni, è buona norma enumerare sempre tutti i campi nelle query.

  • Cosa succede se si decide di aggiungere una colonna TEXT o BLOB in futuro che viene utilizzata per una query particolare?Il tuo SELECT * restituirà i dati aggiuntivi se ne hai bisogno o no.
  • Cosa succede se si rinomina una colonna? Il tuo SELECT * funzionerà sempre, ma il codice relying sarà rotto.
0

Questo è il modo corretto e il più ottimale. Il motivo è che l'unica raccolta dei dati è necessaria in modo che occupi lo spazio corretto (ciò di cui hai bisogno) nella memorizzazione dei dati prima di ottenere i risultati.

SELECT Id, Forename, Surname 
FROM Person 
WHERE PersonName Like(‘%frank%’) 

Questo non è corretto in quanto riprende i campi non utilizzati che occupa più spazio per eseguire la query che rallenta i risultati. Anche se sei fortunato e utilizzi tutti i campi della tua query, è meglio elencarli singolarmente. Questo chiarirà la query e quali dati devono essere restituiti a qualsiasi altro sviluppatore che potrebbe aver bisogno di modificare la query in futuro.

SELECT * 
FROM Person 
WHERE PersonName Like(‘%frank%’) 
2

Per i progetti di piccole dimensioni, in genere è possibile utilizzare select *. È "giusto" non farlo, però. Non noterai alcuna differenza di velocità apprezzabile per una tabella in una query non indicizzata ... l'unica cosa che stai facendo apprezzabilmente è usare più larghezza di banda per le colonne che non leggi.

Detto questo, noterete una differenza nelle query solo indice in cui state premendo l'intera tabella quando avete solo bisogno di colpire l'indice. Questo sopraggiungerà in particolare quando si stanno unendo.

Select * ha comunque usi e, se lo si utilizza correttamente (ad esempio, in combinazione con una cache, assicurandosi che sia select table.* e indirizzando i risultati per nome colonna) è possibile ridurre le query effettuate dall'applicazione.

5

Ho intenzione di andare contro corrente e dire che dovresti andare con la selezione *. Penso che l'ottimizzazione prematura sia la radice di molti problemi, e potresti scoprire che non influisce sulle tue prestazioni quando arrivi al reale utilizzo. Certo, dal libro è più lento, deve essere, ma ciò non significa che la differenza sia importante nella pratica.

Qualcosa di cui essere a conoscenza, tuttavia, è che alcuni motori SQL (sicuramente MS-SQL) memorizzeranno nella cache la select *, quindi se si sta usando un'istruzione preparata, o una vista o una stored procedure che lo ha, e cambia lo schema della tabella, non prenderà in considerazione la modifica a meno che la vista o la sp vengano ricompilate, quindi è una buona ragione per evitare di farlo se non si eseguono queste query dinamicamente.

E, naturalmente, questo varia a seconda del motore del database, quindi è necessario eseguire un piccolo test di carico per assicurarsi che l'hit non sia ovviamente di grandi dimensioni.

0

l'unica volta che io uso "select *" non evento è in realtà un "select *"

specificamente:

select count(*) from table

non è la stessa come

select count(ID) from table

la per prima cosa restituisce il numero di righe nella tabella
ma il secondo restituisce il numero di righe con un valore ID NOT NULL.

una sottile distinzione ma che vale la pena ricordare.

+0

Un altro uso accettabile di SELECT * si trova nella sottoquery di una clausola EXISTS. – onedaywhen

0

SELECT * sarà più lento poiché deve trasferire più dati. Anche per altri motivi già menzionati. Diventa davvero un problema quando si uniscono le tabelle da quando si inizia ad aggiungere molte più colonne, quando in realtà tutto ciò che si vuole fare è unirsi in modo da poter filtrare.

Se davvero si vuole usare *, specificare la tabella che si desidera che tutte le colonne, come SELEZIONA persona. * FROM persona ...

Che vi restringere la quantità di dati restituiti e lo rende un po ' più leggibile.

0

Lasciami giocare ai diavoli avvocato e suggerire uno scenario in cui SELECT * è una scelta migliore. Supponiamo di creare un'interfaccia utente dove prendi i risultati del set di dati e visualizzali sotto forma di tabella o griglia. È possibile creare le colonne nell'interfaccia utente in modo che corrispondano alle colonne nel set di dati e selezionare SELECT * FROM MyView.

Utilizzando una vista nel database si ha il controllo completo su quali colonne vengono restituite dalla query e l'interfaccia utente può essere abbastanza dinamica da visualizzare tutte le colonne. Le modifiche alla vista si rifletteranno immediatamente nell'interfaccia utente senza ricompilare e re0 Ovviamente suggerirei di seguire il consiglio precedente e specificare tutte le colonne nella definizione della vista.

Ho solo pensato di aggiungere che, a volte, le persone si fanno dogmatiche nel seguire certe regole e dimenticare che il contesto è importante.

Problemi correlati