Sqlserver
 sql >> Database >  >> RDS >> Sqlserver

Migliora le prestazioni delle query di SQL Server su tabelle di grandi dimensioni

Risposta semplice:NO. Non puoi aiutare le query ad hoc su una tabella di 238 colonne con un fattore di riempimento del 50% sull'indice cluster.

Risposta dettagliata:

Come ho affermato in altre risposte su questo argomento, il design dell'indice è sia arte che scienza e ci sono così tanti fattori da considerare che ci sono poche, se non nessuna, regole rigide e veloci. È necessario considerare:il volume delle operazioni DML rispetto a SELECT, il sottosistema del disco, altri indici/trigger sulla tabella, la distribuzione dei dati all'interno della tabella, sono query che utilizzano condizioni SARGable WHERE e molte altre cose che non riesco nemmeno a ricordare bene ora.

Posso dire che nessun aiuto può essere fornito per domande su questo argomento senza una comprensione della tabella stessa, dei suoi indici, trigger, ecc. Ora che hai pubblicato la definizione della tabella (ancora in attesa sugli indici ma la definizione della tabella da sola punta a 99% del problema) posso offrire alcuni suggerimenti.

Innanzitutto, se la definizione della tabella è accurata (238 colonne, 50% di fattore di riempimento), puoi praticamente ignorare il resto delle risposte / consigli qui;-). Mi dispiace essere poco politico qui, ma sul serio, è una caccia all'oca senza conoscere i dettagli. E ora che vediamo la definizione della tabella, diventa un po' più chiaro il motivo per cui una semplice query richiederebbe così tanto tempo, anche quando le query di test (Aggiornamento n. 1) sono state eseguite così rapidamente.

Il problema principale qui (e in molte situazioni di scarse prestazioni) è la cattiva modellazione dei dati. 238 colonne non sono proibite così come non è proibito avere 999 indici, ma generalmente non è molto saggio.

Raccomandazioni:

  1. In primo luogo, questo tavolo ha davvero bisogno di essere rimodellato. Se questa è una tabella di data warehouse, allora forse, ma in caso contrario questi campi devono davvero essere suddivisi in più tabelle che possono avere tutte la stessa PK. Avresti una tabella dei record principali e le tabelle figlie sono solo informazioni dipendenti basate su attributi comunemente associati e il PK di quelle tabelle è lo stesso del PK della tabella principale e quindi anche FK della tabella principale. Ci sarà una relazione 1 a 1 tra le tabelle principali e tutte secondarie.
  2. L'uso di ANSI_PADDING OFF è inquietante, per non dire incoerente all'interno della tabella a causa delle varie aggiunte di colonne nel tempo. Non sono sicuro di poterlo risolvere ora, ma idealmente avresti sempre ANSI_PADDING ON o almeno avere la stessa impostazione su tutti gli ALTER TABLE dichiarazioni.
  3. Considera la creazione di 2 gruppi di file aggiuntivi:tabelle e indici. È meglio non mettere le tue cose in PRIMARY poiché è lì che SQL SERVER archivia tutti i suoi dati e metadati sui tuoi oggetti. Crei la tua tabella e l'indice cluster (poiché sono i dati per la tabella) su [Tables] e tutti gli indici non cluster su [Indexes]
  4. Aumenta il fattore di riempimento dal 50%. Questo numero basso è probabilmente il motivo per cui lo spazio dell'indice è maggiore dello spazio dati. Eseguire una ricostruzione dell'indice ricreerà le pagine di dati con un massimo di 4k (su una dimensione totale della pagina di 8k) utilizzate per i tuoi dati in modo che la tua tabella sia distribuita su un'ampia area.
  5. Se la maggior parte o tutte le query hanno "ER101_ORG_CODE" nel WHERE condizione, quindi considera di spostarla nella colonna iniziale dell'indice cluster. Supponendo che venga utilizzato più spesso di "ER101_ORD_NBR". Se "ER101_ORD_NBR" viene utilizzato più spesso, mantienilo. Sembra solo, supponendo che i nomi dei campi significhino "OrganizationCode" e "OrderNumber", che "OrgCode" sia un raggruppamento migliore che potrebbe avere più "OrderNumbers" al suo interno.
  6. Punto minore, ma se "ER101_ORG_CODE" è sempre di 2 caratteri, usa CHAR(2) invece di VARCHAR(2) poiché salverà un byte nell'intestazione della riga che tiene traccia delle dimensioni della larghezza variabile e si somma su milioni di righe.
  7. Come altri hanno già detto, usando SELECT * danneggerà le prestazioni. Non solo perché richiede a SQL Server di restituire tutte le colonne e quindi è più probabile che esegua una scansione dell'indice in cluster indipendentemente dagli altri indici, ma richiede anche del tempo a SQL Server per passare alla definizione della tabella e tradurre * in tutti i nomi delle colonne. Dovrebbe essere leggermente più veloce per specificare tutti i 238 nomi di colonna in SELECT elenco anche se ciò non aiuterà il problema di scansione. Ma hai mai davvero bisogno di tutte e 238 le colonne contemporaneamente?

Buona fortuna!

AGGIORNAMENTO
Per completezza della domanda "come migliorare le prestazioni su una tabella di grandi dimensioni per query ad hoc", va notato che sebbene non sia di aiuto per questo caso specifico, SE qualcuno sta utilizzando SQL Server 2012 (o più recente quando arriva quel momento) e SE la tabella non viene aggiornata, l'utilizzo di Columnstore Indexes è un'opzione. Per maggiori dettagli su questa nuova funzionalità, guarda qui:http://msdn.microsoft.com/en-us/library/gg492088.aspx (credo che siano stati fatti per essere aggiornabili a partire da SQL Server 2014).

AGGIORNAMENTO 2
Ulteriori considerazioni sono:

  • Abilita la compressione sull'indice cluster. Questa opzione è diventata disponibile in SQL Server 2008, ma come funzionalità solo per Enterprise Edition. Tuttavia, a partire da SQL Server 2016 SP1 , La compressione dei dati è stata resa disponibile in tutte le edizioni! Consulta la pagina MSDN per la compressione dei dati per i dettagli sulla compressione di righe e pagine.
  • Se non puoi utilizzare la compressione dei dati o se non fornisce molti vantaggi per una tabella particolare, SE hai una colonna di tipo a lunghezza fissa (INT , BIGINT , TINYINT , SMALLINT , CHAR , NCHAR , BINARY , DATETIME , SMALLDATETIME , MONEY , ecc) e ben oltre il 50% delle righe sono NULL , quindi considera l'abilitazione di SPARSE opzione che è diventata disponibile in SQL Server 2008. Per i dettagli, vedere la pagina MSDN per Usa colonne sparse.