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

Restringere i tipi di dati su una tabella molto grande

Prima di tutto, grazie per averlo fatto. È una vittoria così ovvia che molti non vedrebbero molto valore, ma ne varrà la pena :). Rendere il mondo un po' più sano.

Riguardo a IsActive essere un booleano. La mia ipotesi è che stai pensando di renderlo un BIT campo. Potrebbe essere la strada da percorrere, ma a volte è meglio usare TINYINT poiché esiste la possibilità di espandere il significato in più di 2 stati. In tal caso diventa davvero più di StatusID . Di solito si tratta di qualcosa che inizia semplicisticamente come Attivo / Non attivo , ma in seguito forse Eliminato e/o altri. Dal punto di vista del dimensionamento, TINYINT è sempre 1 byte. D'altra parte, BIT è 1 byte per un massimo di 8 BIT campi . Significato, un BIT il campo è 1 byte, 2 BIT campi è anche un byte, e così via fino a 8 BIT campi memorizzati in un singolo byte. Quindi, non c'è risparmio di spazio scegliendo BIT su TINYINT quando la tabella ha solo 1 BIT campo. Solo qualcosa da considerare.

Fare un ALTER TABLE è un po' troppo per un grande tavolo, come hai visto. Un'opzione, anche se non eccezionale, è aggiungere un NOT NULL campo--Number_1new --con un DEFAULT valore (questo sarà istantaneo a causa dell'impostazione predefinita, almeno a partire da SQL 2012) che nessuno di loro avrebbe naturalmente (ad es. 255), e quindi migrando lentamente i valori, in un ciclo, come in:

UPDATE TOP (5000) tab
SET tab.Number_1new = tab.Number_1
FROM [table] tab
WHERE tab.Number_1new = 255;

E quando ciò è fatto, fai:

sp_rename 'table.Number_1', 'Number_1old', 'COLUMN';
sp_rename 'table.Number_1new', 'Number_1', 'COLUMN';

Ovviamente, è meglio avvolgerlo in una TRANSAZIONE e quello in un TRY / CATCH. Quando il codice correlato è stato aggiornato e tutto è stato testato e i dati sembrano a posto, puoi eliminare il Number_1old colonna.

Tuttavia, il modo migliore che ho trovato è creare una nuova tabella, trasferire lentamente i dati, quindi scambiare le tabelle e il codice contemporaneamente. Ho descritto i passaggi in un articolo su SQL Server Central:Ristruttura 100 milioni di righe (o altro) Tabelle in secondi. SRSLY! (richiesta registrazione gratuita). Nel caso in cui ci siano problemi con l'accesso a quell'articolo, ecco i passaggi di base:

  1. Crea una nuova tabella con la struttura ideale--[tableNew]. Se utilizzi l'edizione Enterprise, considera di abilitare la compressione ROW o PAGE poiché a volte possono essere d'aiuto. Ma per favore prima fai qualche ricerca perché ci sono alcune situazioni in cui hanno un effetto negativo. C'è documentazione su MSDN per aiutarti a capirlo così come alcuni strumenti per aiutare a stimare il potenziale risparmio. Ma anche se abiliti la compressione, non vedrei quell'azione come una sostituzione del progetto che stai facendo qui.
  2. Aggiungi un trigger AFTER UPDATE, DELETE su [tabella] per mantenere le modifiche sincronizzate (ma non c'è bisogno di preoccuparsi delle nuove righe)
  3. Crea un processo di SQL Agent che si sposta sulle righe mancanti in batch. Fallo in un ciclo che esegue un INSERT INTO [tableNew] (Columns) SELECT TOP (n) Columns FROM [table] WHERE ?? ORDER BY ??
  4. Le clausole WHERE e ORDER BY dipendono dalla situazione. Dovrebbero essere orientati a sfruttare al meglio l'indice cluster. Se l'indice cluster della nuova tabella è strutturalmente lo stesso della vecchia/corrente tabella, all'inizio di ogni ciclo puoi ottenere il MAX([id]) da [tableNew] e usarlo per ottenere la tabella WHERE table.[id] > @MaxIdInTableNew ORDER BY table.[id] .
  5. Crea la nuova tabella, attiva la tabella corrente e il processo di SQL Agent circa una settimana prima di dover eseguire il cut-over completo. Quel lasso di tempo potrebbe cambiare in base alla tua situazione, ma assicurati solo di concederti un sacco di tempo. È molto meglio che il lavoro finisca la migrazione delle righe e abbia solo pochi gocciolamenti alla volta invece di essere 100.000 in meno rispetto al set completo poiché il rilascio dovrebbe iniziare.
  6. Se il piano prevede la migrazione delle altre tabelle correlate (i riferimenti PK per i due FK che vuoi trasformare in INT s), quindi crea quei campi qui INT ora e semplicemente non aggiungere l'FK fino a quando le altre tabelle non vengono migrate in modo che abbiano campi INT come PK. Non vuoi dover ricostruire di nuovo questa tabella solo per apportare la modifica ai campi FK.
  7. Durante il cut-over (in un TRY/CATCH, ovviamente):
    1. INIZIA TRAN
    2. esegui un conteggio finale delle righe su entrambe le tabelle per assicurarti che tutto venga spostato (potresti voler controllare le righe prima del rilascio per assicurarti che il trigger abbia eseguito gli aggiornamenti e le eliminazioni come previsto)
    3. rinomina la tabella corrente in "vecchia"
    4. rinominare la tabella "nuova" per non avere la "nuova"
    5. elimina il processo di SQL Agent (o almeno disabilitalo)
    6. rinominare e dipendenti oggetti come vincoli, ecc
    7. IMPEGNA