Aggiunta di colonne alle tabelle di produzione


28

Qual è il modo migliore per aggiungere colonne a tabelle di produzione di grandi dimensioni su SQL Server 2008 R2? Secondo i libri di Microsoft online:

Le modifiche specificate in ALTER TABLE vengono implementate immediatamente. Se le modifiche richiedono modifiche delle righe nella tabella, ALTER TABLE aggiorna le righe. ALTER TABLE acquisisce un blocco di modifica dello schema sulla tabella per assicurarsi che nessun'altra connessione faccia riferimento anche ai metadati della tabella durante la modifica, ad eccezione delle operazioni di indice online che richiedono un blocco SCH-M molto breve alla fine.

(Http://msdn.microsoft.com/en-us/library/ms190273.aspx)

Su una tabella di grandi dimensioni con milioni di righe, questo può richiedere del tempo. Prendere un'interruzione è l'unica opzione? Qual è il modo migliore per gestire questo tipo di situazione?


1
Articolo recente su questo problema: sqlservercentral.com/articles/Change+Tracking/74397
8kb

Risposte:


27

"Dipende"

Se aggiungi una colonna che non richiede l'aggiunta di dati alle righe, può essere abbastanza veloce.

Ad esempio, l'aggiunta di un int o char richiede movimenti fisici delle righe. L'aggiunta di un varchar nullable senza impostazione predefinita non dovrebbe (a meno che la bitmap NULL non debba espandersi)

È necessario provarlo su una copia ripristinata della produzione per ottenere un preventivo

La creazione di una nuova tabella, la copia e la ridenominazione potrebbero richiedere più tempo se è necessario aggiungere nuovamente indici e chiavi su una tabella da un miliardo di righe.

Ho cambiato miliardi di tabelle di righe che impiegavano pochi secondi per aggiungere una colonna nullable.

Ho detto di fare prima un backup?


2
+1 sul backup. e assicurati di avere anche abbastanza spazio nel registro.
SqlACID,

Puoi chiarire perché l'aggiunta di un int o char richiede movimenti di riga fisici?
sh-beta,

5
Intendevi "non" richiedere l'aggiunta di dati alle righe nella seconda riga?
Ben Brocka,

21

Se la colonna è NULLable, l'impatto dovrebbe essere trascurabile. Se la colonna non può essere NULL e il valore deve essere impostato, può essere abbastanza diverso. Quello che farei in questo caso è, invece di aggiungere un vincolo non nullo e predefinito in un colpo solo, aggiungendo effettivamente dati ad ogni riga:

  • aggiungi la colonna come NULLable - dovrebbe essere veloce nella maggior parte dei casi
  • aggiorna i valori ai valori predefiniti
    • puoi farlo in batch se necessario
    • puoi anche usarlo per applicare la logica condizionale in cui alcune righe potrebbero non ottenere quelle predefinite
  • aggiungere i vincoli non nulli / predefiniti
    • questo sarà più veloce quando nessuno dei dati è NULL, ma dovrebbe essere comunque misurabile

Concorda con @gbn che puoi provarlo ripristinando una copia della produzione e provandola lì ... avrai una buona idea dei tempi (supponendo che l'hardware sia in qualche modo simile) e puoi anche vedere l'impatto sul registro delle transazioni.


Per quanto riguarda l'ultimo bit: •add the not null/default constraintsnon sono sicuro che non ci sia un potenziale problema con questo ... Quando MSSQL (anche 2008R2) cambia una colonna non nulla in nulla, se metti una traccia puoi vederla effettivamente sotto le copertine facendo un aggiornamento completo di ogni riga della tabella, cioè update table1 set column1 = column1suppongo che stia facendo la verifica non nulla in un modo completamente idiota. Questa transazione ha una dimensione doppia della tabella (prima e dopo le pagine), quindi per una tabella DW può essere enorme. In precedenza abbiamo dovuto effettuare il bcp dei dati in uscita, troncare, apportare modifiche null a non null, quindi effettuare il bcp in.

Se qualcuno conosce un modo per aggirare questo, adoro sapere ... Al contrario, in Oracle, la modifica di null in non null fa un blocco, quindi una selezione per verificare nessun non nullo, quindi un aggiornamento istantaneo di metadati.

Ehi @Mike, sembra una buona domanda a sé stante.
Derek Downey,

4

Hai considerato:

  1. Creazione di una nuova tabella che include le modifiche alla definizione della tabella.
  2. Inserimento nella nuova definizione di tabella selezionando dalla tabella originale.
  3. Rinominare la tabella originale in _orig e quindi rinominare la nuova tabella con il nome della tabella originale.

Lo svantaggio è che è necessario disporre di spazio sufficiente nel database per apportare questa modifica. Potrebbe essere necessario un blocco di lettura sul tavolo per evitare letture sporche.

Tuttavia, si minimizza l'impatto per gli utenti finali se esiste la possibilità o la necessità di accedere contemporaneamente alla tabella originale. Dovrebbe anche ridurre al minimo la durata del blocco.


Non avresti bisogno di un blocco di scrittura , piuttosto che leggere? Va bene per gli utenti vedere i dati nella vecchia tabella, semplicemente non vuoi che commettano eventuali modifiche che verrebbero sovrascritte al termine dello swap del buffer.
Jon of All Trades,

Questo è stato il mio pensiero con il mio cappello del data warehouse su dove le modifiche possono essere controllate un po 'più facilmente. In una situazione OLTP, hai ragione, sarebbe necessario un blocco in scrittura per evitare di apportare modifiche alla tabella.
RobPaller,
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.