Ricostruisci indice chiave primaria molto grande


13

Ho un database SQL ospitato su Azure. Il problema è che la dimensione sta andando fuori controllo, posso vedere una frammentazione fino al 99% negli indici cluster della chiave primaria.

Sono in grado di ricostruire tutti gli altri indici con l' online=onopzione e non influirà sulle prestazioni. La dimensione di uno degli indici cluster PK è maggiore di 200 GB e per questo REBUILD...WITH (ONLINE=ON)causa un blocco.

Abbiamo utenti da tutti i fusi orari che accedono al sito, quindi davvero, non riesco a trovare un momento in cui posso ricostruire l'indice offline.

Qual è la migliore strategia per ricostruire indici di grandi dimensioni senza tempi di inattività nel sito?

Credo che riorganizzare non aiuterà poiché la frammentazione è del 99%. Il problema è che il tavolo viene bloccato anche con online. Il problema principale è che l'indice è maggiore di 200 GB. La chiave primaria è un numero intero.


4
@Techy, anche con elevata frammentazione, REORGANIZEridurrà la frammentazione delle pagine fogliari e lo spazio compatto come REBUILD, in modo meno efficiente. Sei sicuro che le grandi dimensioni siano dovute alla frammentazione? Qual è il fattore di riempimento?
Dan Guzman,

Sai cosa sta causando la frammentazione? Dopo quanto tempo dalla ricostruzione tornerai al punto 1? Puoi pubblicare maggiori informazioni sul tuo tavolo?
pacificamente

2
@Techy Ho modificato la domanda per aggiungere alcune informazioni aggiuntive in base ai tuoi commenti. Sarebbe utile se includessi anche la definizione della tabella nella domanda e ulteriori dettagli relativi a "la tabella viene bloccata anche quando [ricostruzione] online". Che tipo di attese stai vedendo?
Due

Risposte:


9

Anche se è un po 'tardi, presenterò una risposta con la speranza che possa aiutare o almeno respingere alcune idee / commenti aggiuntivi su questo problema perché penso che sia una buona domanda.

Innanzitutto, e non so se lo stai facendo o no, ma per favore non dare per scontato che alti livelli di frammentazione sull'indice causino sempre scarse prestazioni. Le statistiche non aggiornate (ad es. Sys.dm_db_stats_properties ) e grandi quantità di spazio bianco per pagina (ovvero avg_page_space_used_in_percent nella colonna sys.dm_db_index_physical_stats dmv ) detengono più rilevanza riguardo alle prestazioni rispetto alla sola frammentazione. Sì, gli indici altamente frammentati genereranno più read-ahead e in genere vengono visualizzate statistiche obsolete e livelli più elevati di spazio bianco per pagina accoppiati con la frammentazione, ma la frammentazione non è direttamente legata alle ottimizzazioni del piano di query né alla quantità di memoria che carica l'indice dal disco consumerà effettivamente. I piani di query sono influenzati dalle statistiche e il footprint della memoria si gonfia con più spazio bianco . Ad esempio, un indice frammentato al 99% ma con una media inferiore al 5%. lo spazio bianco e le statistiche aggiornate probabilmente non causano drastici problemi di prestazioni rispetto a un cattivo piano di esecuzione a causa di statistiche obsolete o paging costante di un indice che è troppo grande per adattarsi completamente alla memoria perché c'è una quantità significativa di spazio bianco presente per pagina.

Se la frammentazione è davvero un problema , puoi ridurla, ONLINE, emettendo una ALTER INDEX ... REORGANIZEdichiarazione identificata da Dan Guzman nei commenti. Ciò non creerà un indice più snello come REBUILDun'operazione, ma ridurrà la frammentazione. La chiave qui è identificare le finestre di utilizzo inferiore sul database ed eseguirlo quindi. Questo potrebbe richiedere 15 minuti o più ore, ovviamente più è lungo, meglio è, ma la chiave qui è che questa operazione non esegue il rollback e mantiene i progressi fatti anche se la uccidi a metà dell'esecuzione.

Se, in un mondo perfetto in cui è stata eliminata la tua frammentazione, avrebbe più senso utilizzare il partizionamento su questa tabella? Il database SQL di Azure consente il partizionamento delle tabelle e Microsoft ha un ottimo articolo che delinea alcune strategie di partizionamento per il database SQL di Azure . Se i tuoi dati non sono volatili, il partizionamento può aiutare a ridurre le esigenze di manutenzione e, se abbinato a Compressione tabella , potresti anche essere in grado di ridurre anche il tuo spazio di archiviazione complessivo. La precedente risposta di Alberto Murillo allude all'utilizzo del partizionamento orizzontale basato su un'area dati e questo approccio può aiutarti a creare alcune finestre di manutenzione per te poiché i tuoi dati sarebbero più specifici a livello regionale anziché globale.

Il passaggio a una tabella partizionata non sarà facile con la tua attuale assenza di finestre di manutenzione, ma potresti essere in grado di utilizzare un approccio delineato da Maria Zakourdaev che utilizza viste partizionate nella parte superiore della tabella corrente e una nuova tabella partizionata per iniziare il partizionamento dati futuri. Col passare del tempo (e si spera che i tuoi vecchi dati vengano eliminati), puoi infine passare completamente alla tabella partizionata. Ancora una volta, non conosco i tuoi dati o la tua applicazione, ma forse questo approccio è qualcosa che puoi impiegare.


4

Innanzitutto, è importante considerare se la frammentazione è importante.

Se la query esegue solo ricerche a riga singola, potresti non notare affatto la frammentazione. Nelle moderne SAN, la memorizzazione nella cache a livello di SAN può rendere gli IO fitologici abbastanza veloci da non importare la frammentazione. Su SSD, il modello I / O casuale causato dalla scansione di un indice frammentato può effettivamente comportare prestazioni migliori rispetto ai dati non frammentati.

Spesso, le persone notano che la riqualificazione di un indice ha risolto un problema di prestazioni. La ricostruzione di un indice crea anche nuove statistiche. Può darsi che la vera correzione siano nuove statistiche, non la ricostruzione dell'indice. UPDATE STATISTICS...WITH FULLSCANpuò essere un modo più economico, più veloce e meno invadente per risolvere lo stesso problema di prestazioni.

Se non si verificano problemi causati dalla frammentazione, è possibile che si impieghi tempo e sforzi significativi senza ottenere alcun guadagno effettivo.

In secondo luogo, ci sono due tipi di frammentazione:

  1. Frammentazione fisica. Questo è ciò che la maggior parte delle persone pensa quando pensa alla frammentazione. Le pagine sono fuori servizio e devono essere riordinate. Durante la scansione di un indice questo tipo di frammentazione può talvolta rappresentare un problema. In genere ho notato che questo ha il maggiore impatto sulle prestazioni con letture fisiche . Se stai guardando i risultati da sys.dm_db_index_physical_stats, questo numero è la avg_fragmentation_in_percentcolonna.

  2. Frammentazione a bassa densità. Questa frammentazione è causata da pagine riempite solo parzialmente di dati. Hai una bassa densità di dati perché i tuoi dati sono distribuiti su più pagine del necessario. Di conseguenza, la lettura dei dati richiede più IO perché i dati sono distribuiti su più pagine del necessario. Ciò può influire su letture sia logiche che fisiche. Se stai guardando i risultati da sys.dm_db_index_physical_stats, questo numero è la avg_page_space_used_in_percentcolonna. Questa colonna viene popolata solo quando si utilizza la modalità SAMPLEDo DETAILED.

Quindi cosa fai al riguardo:

Frammentazione fisica : se stai semplicemente inseguendo numeri elevati avg_fragmentation_in_percent, considera davvero se stai perdendo tempo. Assicurarsi di disporre di una query effettiva con prestazioni scarse e utilizzare un ambiente di test per confermare che si sta risolvendo un problema eliminando la frammentazione.

Puoi affrontare la frammentazione fisica facendo ALTER INDEX...REORGANIZE. L' REORGANIZEoperazione è online, spostando le pagine una alla volta per riorganizzarle in ordine fisico. Se si interrompe REORGANIZEun'istruzione a metà strada, qualsiasi lavoro che è già stato eseguito viene mantenuto: verrà eseguito il rollback solo dell'unica pagina attualmente spostata. Esecuzione di operazioni REORGANIZEsu una tabella di grandi dimensioni altamente frammentata può richiedere più spazio per il registro delle transazioni e, in modalità di ripristino completo, può generare una quantità significativa di backup del registro delle transazioni. Potrebbe anche richiedere più tempo per REORGANIZEun indice altamente frammentato che per REBUILDesso.

Vedrai spesso consigli per eseguire un REBUILDsu indici altamente frammentati, piuttosto che un REORGANIZE- Questo perché la ricostruzione da zero può essere più efficiente. Tuttavia, la riorganizzazione può essere un'operazione "più online" ed è talvolta preferita, anche per indici altamente frammentati.

La frammentazione a bassa densità non può essere riparata da REORGANIZE. Può essere risolto solo facendo un ALTER INDEX...REBUILD. Eseguendo l'indice con ONLINE=ON, dovresti essere in grado di ridurre al minimo il blocco. Tuttavia, è REBUILDancora necessario bloccare un attimo per scambiare il vecchio indice con il nuovo indice. Su un sistema molto occupato, il raggiungimento di questo blocco esclusivo a volte può essere un problema. Dovresti essere in grado di confermare se stai riscontrando questo problema usando qualcosa come sp_whoisactive per esaminare il blocco durante la ricostruzione e guardare i dettagli dei blocchi e delle attese. L'uso WAIT_AT_LOW_PRIORITYdell'opzione può essere utile se sai che ci sarà un prossimo periodo di scarso utilizzo e la tua ricostruzione può "intrufolarsi" per questo scambio quando l'attività scende abbastanza da raggiungere quel blocco. Si noti che una lunga durataREBUILDl'operazione sarà anche una transazione aperta a lungo termine. Le transazioni aperte a lungo termine possono avere i loro problemi, legate all'uso / al riutilizzo del registro delle transazioni. Se si utilizza il mirroring o i gruppi di disponibilità, ci sono anche considerazioni per ripetere il registro delle transazioni nella replica secondaria.


La frammentazione a bassa densità (detta anche "frammentazione interna") è spesso corretta da a REORGANIZE. Dal BOL : "La riorganizzazione compatta anche le pagine dell'indice". Bene, fintanto che l'attuale FILLFACTOR dell'indice consentirà la densità che stai cercando.
Granger,

2

Avviso

Dopo questo commento:

Perderai le righe inserite durante la copia. Se si desidera impedire ciò bloccando la tabella, si ottiene lo stesso problema dell'OP indicato nella sua domanda. Anche 200Gb non verranno gratis :-) - Marco, 5 settembre 17 alle 11:18

... Vedo come questo approccio non funzionerà.

Lascerò questa risposta come esempio di cosa non fare.


Se hai 200+ GB di riserva gratuiti nel tuo DB di Azure, puoi ottenere di nascosto con il "ricostruisci", copiando i tuoi dati in una tabella completamente nuova e ordinandoli lì.

Provare:

  • copiando il tuo LiveTablein un vuotoNewTable
  • copiando LiveTablenel fileNewTable
  • rinominando LiveTableinOldTable
  • rinominando NewTableinLiveTable

Ovviamente, usa il nome del tuo tavolo invece di LiveTable.


Oreo, userei lo stesso approccio come te. Anche quando sono presenti righe inserite durante la copia, è comunque possibile aggiungerle successivamente quando la tabella nuova è stata rinominata in tabella live. Il problema principale che eviti qui è il tempo morto prolungato. Potresti persino bcp (copia i / o in). Non è una cattiva idea, quindi non capisco neanche il downvote :-)
Koen D

1

Idealmente, se un indice è ben progettato, non dovremmo aver bisogno di giocherellare con il meccanismo di blocco.

Mi sembra che dovrai accettare il blocco per deframmentare l'indice cluster. Se c'è una buona possibilità che ciò accada di nuovo, allora guarda la riprogettazione dell'indice cluster (dovrebbe essere stretto, unico, statico e in costante aumento).

Non sono sicuro di quale versione di SQL Server stai utilizzando, ma potresti provare quanto segue nel 2012:

  • SET DEADLOCK_PRIORITY LOW - Questo dice al motore che la ricostruzione dell'indice dovrebbe essere la vittima del deadlock quando / se si verifica.

  • MaxDOP = 1 - Il valore MaxDOP limita il numero totale di CPU logiche utilizzate in parallelo per creare l'indice (dal 2005 in poi - solo versione Enterprise).

Puoi anche modificare la configurazione dei blocchi di pagina / riga, ma non lo farei senza test. Potresti semplicemente peggiorare il blocco, soprattutto se si tratta di un indice mal progettato.

A partire dal 2014, vi è la seguente opzione che dice sostanzialmente al motore di consentire ad altre sessioni di procedere e all'operazione dell'indice online di attendere:

(WAIT_AT_LOW_PRIORITY (MAX_DURATION = 1 MINUTES, ABORT_AFTER_WAIT = SELF))

0

Ho usato lo stesso approccio di Oreo sopra descritto con grande successo! L'unica cosa che manca è che è necessario eseguire uno script di aggiornamento dopo aver copiato i dati e aver effettuato l'ultima ridenominazione.

L'aggiornamento sarà simile al seguente:

Insert from OldTable into LiveTable
  Where not exists (select From OldTable Where LiveTable.Key = OldTable.Key)

Se Key è una colonna Identity, è necessario utilizzare un approccio leggermente diverso.


Come indicato nella risposta di Oreo, il suo metodo non funzionerà se ci sono ancora dati aggiunti alla tabella originale, a meno che tu non blocchi la tabella originale che
vanifica

-2

Prova a usare lo sharding per distribuire geograficamente i dati del tuo database. Sarai quindi in grado di identificare finestre di manutenzione diverse per ogni posizione geografica e il tempo necessario per effettuare la manutenzione sarà più breve. Ciò migliorerà anche le prestazioni. Puoi saperne di più su questo articolo. Non aspettare che il database si ingrandisca.

Con database di grandi dimensioni e utenti connessi 24 x 7, è necessario utilizzare la riorganizzazione dell'indice e aggiornare solo le statistiche che devono essere aggiornate (sp_updatestats) per ridurre al minimo il tempo necessario per la manutenzione e l'impatto per gli utenti.

Spero che sia di aiuto.

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.