2009-09-16 9 views
15

Ho una tabella utente in cui sono presenti un nome utente e colonne di applicazione. Nome utente può ripetere, ma combinazione di nome utente + applicazione è unico nel suo genere, ma non ho il vincolo univoco impostato sul tavolo (per le prestazioni)Effetto delle prestazioni dell'utilizzo di TOP 1 in una query SELECT

Domanda: ci sarà alcuna differenza (performance-saggio) tra:

SELECT * FROM User where UserName='myuser' AND Application='myapp' 

E -

SELECT TOP 1 * FROM User where UserName='myuser' AND Application='myapp' 

Come combinazione di nome utente + applicazione è unico, entrambe le query saranno sempre tornare non più di un record, in modo TOP 1 non influisce sul risultato. Ho sempre pensato che l'aggiunta di TOP 1 accelerasse davvero le cose man mano che il server SQL smetteva di cercare una trovata, ma di recente ho letto in un articolo che l'uso di TOP rallenterebbe davvero e si consiglia di evitare, anche se non lo hanno spiegato perché.

Eventuali commenti?

Grazie! Andrey

+0

Grazie per la modifica, Joel - per qualche motivo non ero in grado di fare le query come linee di codice, vorrei selezionarle e fare clic sull'icona "codice" e non sarebbe successo nulla. – Andrey

+0

Andrey, fai clic sull'icona prima di inserire il codice. Il trucco è che qualsiasi riga che inizia con quattro spazi viene interpretata come codice. Semplicemente seleziono il mio codice in SSMS e lo indentro. Questo mi dà una formattazione perfetta. (Ho impostato SSMS per utilizzare spazi anziché caratteri di tabulazione.) –

risposta

10

È possibile ottenere alcune differenze di prestazioni semplicemente utilizzando top, ma le prestazioni reali si ottengono utilizzando gli indici.

Se si dispone di un indice per i campi Nome utente e Applicazione, il database non deve nemmeno toccare la tabella finché non ha isolato il singolo record. Inoltre, dalle statistiche della tabella è già noto che i valori sono univoci, pertanto l'utilizzo di top non fa alcuna differenza.

+0

Creare un indice sulle due colonne è una buona idea, ma non voglio creare un indice univoco, poiché rallenterà gli inserimenti, che sono una parte critica dell'app. – Andrey

+0

Sai che cambiare l'indice in univoco rallenta gli inserti (su un indice non univoco) o sospetti solo che lo farà? Se si presuppone l'unicità, è necessario eseguirne il backup con un indice univoco. –

+0

Un indice univoco rallenta gli inserimenti in quanto deve verificare l'esistenza prima di inserirlo, ma la differenza dovrebbe essere piuttosto piccola. È possibile ottenere prestazioni di lettura un po 'migliori da un indice univoco, ma il vantaggio principale è che ha garantito l'integrità nella tabella. – Guffa

15

Se c'è più di una riga nei risultati e nessuna clausola ORDER BY, la "TOP 1" fa risparmiare un sacco di lavoro per il server. Se c'è un ordine per clausola, il server deve comunque materializzare l'intero set di risultati, e se c'è solo una riga, in realtà non cambia nulla.

+0

Restituirà sempre una o nessuna riga poiché la combinazione di Nome utente e Applicazione è univoca. Quindi capisco correttamente che TOP 1 non farà assolutamente alcuna differenza nel mio caso sopra? – Andrey

+0

Non direi "zero". Gli ottimizzatori di query sono pignoli, quindi inserisco alcune parole di donnola come "probabilmente banale se non ce ne sono". –

+2

Farà la differenza nel mondo per alcuni valori, nessuno per gli altri. Quando chiedi all'utente e all'app che è il primo nell'ordine fisico nella tabella, il TOP 1 sembrerà miracoulos poiché interromperà la scansione dopo un record. Quando chiedi all'utente e all'app vicino alla fine del b-tree, il TOP 1 non farà alcuna differenza. Quello di cui hai veramente bisogno sono gli indici. –

4

Penso che dipenda dal piano di esecuzione della query generato da SQL ... In passato su versioni precedenti di SQL Server ho visto l'utilizzo di un "TOP" superfluo che offre vantaggi prestazionali definiti con query complesse con molti join. Ma sicuramente non in tutti i casi.

Immagino che il miglior consiglio che posso dare sia di provarlo caso per caso.

1

si dice che non si applica il vincolo, che si traduce non esiste un indice univoco su (NomeUtente, Applicazione) o (Applicazione, NomeUtente). La query può utilizzare un percorso di accesso che cerca su UserName o Application? In altre parole, qualcuna di queste due colonne è indicizzata? In caso affermativo, il piano sceglierà il più selettivo che viene indicizzato e esegue una scansione dell'intervallo, possibilmente un ciclo annidato con una ricerca di segnalibro se l'indice non è in cluster, quindi un filtro. La prima parte interromperà la query dopo che il primo filtro è stato abbinato, ma se questo fa la differenza dipende dalla cardinalità dei dati (quanti record trova la scansione degli intervalli e quanti soddisfano il filtro).

Se non c'è indice, eseguirà una scansione completa in cluster, non importa quale. La prima parte interromperà la scansione alla prima corrispondenza, sia dopo l'elaborazione di 1 record o dopo l'elaborazione di 999 mil. record depdends sul nome utente e sull'applicazione effettivi ...

L'unica cosa che rende una differenza reale è consentire alla query di eseguire una ricerca per entrambi i valori, ad es. avere un indice di copertura Il vincolo sarebbe applicato attraverso un indice di copertura di questo tipo. In altre parole: disattivando il vincolo, presumibilmente per le prestazioni in scrittura, sii pronto a pagare il prezzo alle letture. Questa lettura è importante? Hai effettuato qualche misura per confermare che la scrittura in più dell'indice del vincolo ridurrebbe in modo critico le prestazioni?

Problemi correlati