In che modo i campi INCLUDE di indici di grandi dimensioni influiranno sulle prestazioni del sistema?


15

Questa domanda riguarda le prestazioni dell'indice di SQL Server con un varchar(2000)as INCLUDEin un indice di copertura.

Sto cercando di migliorare le prestazioni in un'applicazione di database lenta e instabile. In alcuni casi, i dati si accede attraverso stringhe di grandi dimensioni varchar, con le query tra cui operazioni di stringa multple come SUBSTRING(), SPACE()e DATALENGTH(). Ecco un esempio semplificato di accesso;

update fattable set col3 =  
   SUBSTRING(col3,1,10) + '*' + 
   SUBSTRING(col3,12,DATALENGTH(col3)-12)
from fattable where substring(col3,10,1) = 'A' and col2 = 2

Lo schema è simile al seguente:

CREATE TABLE [dbo].[FatTable]( 
    [id] [bigint] IDENTITY(1,1) NOT NULL, 
    [col1] [nchar](12) NOT NULL, 
    [col2] [int] NOT NULL, 
    [col3] [varchar](2000) NOT NULL, ... 

È stato definito il seguente indice, con un campo di copertura sulla colonna di testo grande.

CREATE NONCLUSTERED INDEX [IndexCol2Col3] ON [dbo].[FatTable]  ( [col2] ASC ) 
    INCLUDE( [col3] )

Da quello che ho letto è MALE mettere grandi campi di dati in un indice. Ho letto diversi articoli, tra cui http://msdn.microsoft.com/en-us/library/ms190806.aspx che discutono dell'impatto del paging e delle dimensioni del disco sulle prestazioni dell'indice. Detto questo, il piano di query utilizza sicuramente l'indice di copertura. Non ho abbastanza informazioni per determinare quanto questo mi stia effettivamente costando in termini di carico del sistema. So che nel complesso il sistema funziona male e sono preoccupato che questo sia uno dei problemi. Domande:

  • Mettere questa varchar(2000)colonna nell'indice è INCLUDEmai una buona idea?

  • Poiché i INCLUDEcampi sono archiviati in nodi foglia, hanno un impatto notevole sulle prestazioni dell'indice?

Aggiornamento: grazie per le risposte eccellenti! Questa è una domanda ingiusta in un certo senso - come voi ragazzi affermate, non esiste una risposta assolutamente corretta senza statistiche e profilazione effettive. Come tanti problemi di prestazioni, immagino che la risposta sia "dipende".


Quanto durano i valori effettivi? A VARCHAR(2000)che in genere memorizza solo dieci personaggi è una cosa; ben 2.000 byte per record sono qualcos'altro.
Jon of All Trades,

Solo un'osservazione: qualcosa che "profuma" qui è che la colonna di grandi dimensioni può contenere 1) testo libero, nel qual caso le query possono beneficiare di riscritture per utilizzare un indice FULLTEXT o 2) dati in codice "leggibili dall'uomo" (ad es. Ampio intelligente chiavi, come un VIN) che potrebbero trarre vantaggio dalla suddivisione in colonne separate o colonne calcolate persistenti con INDICE. In altre parole, il flusso di intelligenza e i cambiamenti dei dati non sono ben progettati.
Graeme,

1
Sì #Graeme, c'è un cattivo odore qui - penso che si chiami "eredità". Ci sono molti problemi in questo database.
RaoulRubin,

Risposte:


14

Mai è una parola grossa, ma, in generale, no, non metterei un campo varchar (2000) in un INCLUDE.

E sì, il modo in cui i dati vengono archiviati a livello di pagina può influire seriamente sulle prestazioni dell'indice, a seconda di come viene utilizzato l'indice.

Il fatto è che più righe di dati è possibile raggruppare in una pagina, meno pagine devono accedere, più veloce è il sistema, per la maggior parte. L'aggiunta di una colonna molto grande significa meno informazioni memorizzate su una pagina, quindi, in caso di ricerche o scansioni di intervalli, è necessario leggere più pagine per recuperare i dati, rallentando notevolmente le cose.

Per sapere con certezza se si tratta di un problema sulla tua query o sul tuo sistema, dovresti monitorare le letture, in particolare il numero di pagine utilizzate dalla query.


Grazie Grant. Come ho già detto un altro commento, le informazioni sulle buone prestazioni sono scarse, quindi la domanda astratta. Non ho esperienza nel monitoraggio dei costi delle prestazioni delle dimensioni della pagina. La mia idea è che sia un problema, vedrò se riesco a ottenere alcune statistiche.
RaoulRubin,

1
l'impostazione delle statistiche su IO per la query ti dirà molto, letture logiche rappresentano il numero di pagine a cui si accede. È inoltre possibile monitorare sec / read dai contatori di perfmon per ottenere informazioni generali sulle prestazioni.
Grant Fritchey,

6

Puoi rivedere la chiave di indice cluster corrente e forse creare col2invece la chiave di indice cluster? In questo modo si ottiene il comportamento "include" di copertura (poiché gli indici cluster sono sempre "compreso" tutto) senza duplicare i dati. Questo, ovviamente, è soggetto a molti ife but, tuttavia, forse vale la pena considerare. Naturalmente se l'attuale indice cluster sta imponendo un vincolo (chiave primaria, univoco), tale vincolo dovrebbe essere spostato in un indice non cluster.


Il tuo suggerimento sul PK è un'ottima idea, anche se in questo caso non sarò in grado di applicarlo - PK esistente è necessario per altre domande. (Questa è una tecnica che terrò nella cassetta degli attrezzi!)
RaoulRubin,

4

È difficile rispondere. Tutto dipenderà dal rapporto di lettura: scrittura. Hai testato un carico di lavoro o simulato un intero ciclo aziendale su un sistema di test, con e senza la colonna inclusa? La ricerca senza di essa può costare molto, ma se stai aggiornando i dati più spesso di quanto stai leggendo, potrebbe essere ok.


L'aggiornamento generale di lettura e aggiornamento è per lo più bilanciato. Problemi organizzativi e di privacy rendono difficile ottenere statistiche utili e test realistici. Dato che voliamo per lo più ciechi, dobbiamo guardare le cose da un punto di vista astratto (da qui questa domanda). Testare significherà spingere le modifiche alla produzione e osservare i risultati - molto rischioso.
RaoulRubin,

2
E la maggior parte delle letture effettivamente estrae questa VARCHAR(2000)colonna o stai risolvendo le prestazioni di una query molto specifica che non rappresenta la maggior parte delle query? Come suggerisce Grant se questa colonna non viene utilizzata in molte query o causa davvero problemi per le ricerche, probabilmente sarà meglio pagare il prezzo della ricerca quando ne hai bisogno, ma non pagare per lo spazio di archiviazione quando non lo fai . Ancora una volta, è davvero difficile dire da che parte del recinto dovresti essere, dal momento che non abbiamo davvero alcun dettaglio (e ancora più difficile perché non puoi testare - dovresti cercare di risolverlo).
Aaron Bertrand

3

So di essere in ritardo per questa festa, ma vorrei indicizzare esattamente le espressioni usate per localizzare le righe, come la sottostringa (col3,10,1). Se venisse mai usato l'intero col3, indicizzerei CHECKSUM (col3) (comprendendo che ovviamente potrebbero esserci delle collisioni).

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.