Come posso aggiungere una colonna rowversion a una tabella di grandi dimensioni con tempi di inattività minimi


21

Utilizzando SQL Server 2008 e versioni successive, voglio aggiungere una colonna Rowversion a una tabella di grandi dimensioni, tuttavia, quando semplicemente

ALTER TABLE [Tablename]
ADD Rowversion [Rowversion] NOT NULL

Quindi la tabella non è disponibile per gli aggiornamenti per troppo tempo.

Quali strategie posso usare per ridurre questo tempo morto? Prenderò in considerazione qualsiasi cosa. Più semplice è, meglio ovviamente, ma prenderò in considerazione qualsiasi strategia.

Il mio pensiero è che come ultima risorsa, potrei mantenere una tabella di gestione temporanea di copia gestita da trigger e quindi sp_rename la tabella di gestione temporanea nella tabella originale. Ma spero in qualcosa di più semplice / più facile.

Risposte:


26

Prendi in considerazione la creazione di una nuova tabella con lo stesso schema più la colonna rowversion e aggiungi una vista in cima a entrambe le tabelle che uniscono tutte. Chiedi alle persone di utilizzare la vista e scrivere invece di trigger rispetto alle tabelle e alle viste sottostanti.

Gli inserti devono essere inviati alla nuova tabella, gli aggiornamenti devono spostare i dati nella nuova tabella e le eliminazioni devono essere applicate a entrambe le tabelle.

Quindi esegui mosse batch in background, spostando il maggior numero di record alla volta nella nuova tabella. Puoi ancora avere problemi di concorrenza mentre è in corso e alcuni piani di esecuzione craptacular, ma ti consente di rimanere online mentre le mosse stanno accadendo.

Idealmente, inizi il processo un venerdì pomeriggio per ridurre al minimo l'effetto sugli utenti finali e provi a farlo prima di lunedì mattina. Una volta che è a posto, è possibile modificare la vista in modo che punti solo al nuovo tavolo e i piani di esecuzione craptacular scompaiono. Idealmente.

Per evitare l'attivazione dei trigger quando i dati vengono migrati in batch, osservare il numero di righe nelle tabelle eliminate / inserite nel trigger e saltare le attività se si avvicinano al numero di righe nel batch.


Alla fine, Michael ha deciso di saltare la vista (e non di eliminarla dalla tabella originale) per ottenere piani più stabili. Il compromesso conteneva essenzialmente due copie del tavolo. Lo ha trasformato in una serie di post sul blog .


7

Se hai tempo per pianificare in anticipo, c'è una soluzione molto più semplice ... (di solito)

I lunghi blocchi sono quasi certamente causati da spaccature di pagina a livello di archiviazione. Quindi forzali secondo il tuo programma.

  1. Aggiungi una colonna temporanea con supporto NULL con tipo di dati VARBINARY(8).
  2. Trova il tempo di gioco disponibile nel database per aggiornare i batch dei record esistenti con un valore valido per il campo. ( 0x0000000027F95A5Bad esempio)
  3. Gli aggiornamenti imporranno le suddivisioni di pagina necessarie e assegneranno più spazio alla tabella.
  4. Quando sei raggiunto, rilascia la colonna temporanea (non tocca l'archiviazione allocata) e aggiungi la colonna di rowversion.
  5. Nessuna divisione della pagina e un blocco necessario solo per il tempo necessario per popolare i valori.

L'ho usato con successo per aggiungere una colonna rowversion a una tabella di righe 150M in meno di 10 minuti.

Avvertenza ... se si dispone di una tabella con campi varchar di grandi dimensioni (in particolare varchar(max)) SQL Server decide di ricostruire la tabella invece di riutilizzare lo spazio appena disponibile. Sto ancora cercando di trovare un modo per aggirare quello.


Interessante, suppongo di non aver specificato cosa significasse "troppo lungo" nella mia domanda. Se> 30 minuti sono troppo lunghi per il tuo scenario e 10 minuti sono tollerabili, questa soluzione funzionerebbe. Il mio scenario prevedeva il tentativo di ottenere tempi di inattività pari a zero o più specificamente <10 secondi, ottenuto dalla risposta di Brent.
Michael J Swart,

1

Se TIMESTAMPstai aggiungendo è NULLABLE:

  1. Aggiungi una VARBINARY(8)colonna
  2. Popolare con i dati.

Dopo che è stato popolato, nelle istruzioni SQL back to back, DROPla VARBINARY(8)colonna appena aggiunta e popolata e aggiungere la TIMESTAMP NULLcolonna.


Se TIMESTAMPstai aggiungendo è NOT NULLABLE:

  1. Aggiungi una BINARY(8)colonna
  2. Popolare con i dati.

Dopo che è stato popolato, nelle istruzioni SQL back to back, DROPla BINARY(8)colonna appena aggiunta e popolata e la ADD THE TIMESTAMP NOT NULLcolonna.

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.