Domanda

Voglio modificare un campo da una tabella che contiene circa 4 milioni di record.Mi sono assicurato che tutti i valori di questi campi NON siano NULL e desidero ALTERARE questo campo su NON NULL

ALTER TABLE dbo.MyTable
ALTER COLUMN myColumn int NOT NULL

...sembra volerci un'eternità per fare questo aggiornamento.Qualche modo per accelerarlo o sono bloccato a farlo solo durante la notte durante gli orari non lavorativi?

Inoltre ciò potrebbe causare un blocco del tavolo?

È stato utile?

Soluzione

È possibile modificare un campo e renderlo non nulla senza di essa il controllo dei campi. Se siete davvero preoccupati per non farlo fuori ora è possibile aggiungere un vincolo al campo che controlla per assicurarsi che non è nulla, invece. Questo vi permetterà di utilizzare l'opzione di controllo con nessuna, e non l'hanno controllare ciascuno dei 4 milioni di righe per vedere se si aggiorna.

CREATE TABLE Test
(
    T0 INT Not NULL,
    T1 INT NUll 
)

INSERT INTO Test VALUES(1, NULL) -- Works!

ALTER TABLE Test
    WITH NOCHECK
        ADD CONSTRAINT N_null_test CHECK (T1 IS NOT NULL)

    ALTER COLUMN T1 int NOT NULL 

INSERT INTO Test VALUES(1, NULL) -- Doesn't work now!

In realtà ci sono due opzioni (aggiunto un terzo vedere Edit):

  1. Utilizza il vincolo che impedirà eventuali nuove righe vengano aggiornati e lasciare inalterati quelli originali.
  2. Aggiornare le righe che sono nulla a qualcosa d'altro e quindi applicare l'opzione alter non nullo. Questo in realtà dovrebbe essere eseguito nelle ore fuori, a meno che non vi occupate di processi essere bloccati fuori della tabella.

A seconda dello scenario specifico, entrambe le opzioni potrebbe essere migliore per voi. Non vorrei scegliere l'opzione perché devi eseguirlo nelle ore fuori però. Nel lungo periodo, il tempo dedicato aggiornamento nel bel mezzo della notte sarà ben speso paragonato il mal di testa si possibilmente affrontare prendendo una scorciatoia per risparmiare un paio di ore.

Tutto ciò premesso, se avete intenzione di andare con l'opzione due è possibile ridurre al minimo la quantità di lavoro che fate nelle ore fuori. Dal momento che si deve fare in modo di aggiornare le righe per non nullo prima di modificare la colonna, si può scrivere un cursore lentamente (rispetto a fare tutto in una volta)

  1. Passare attraverso ogni riga
  2. Controlla per vedere se è nullo
  3. Aggiornare in modo appropriato. Questo richiederà un bel po ', ma non si blocca l'intero blocco tabella altri programmi di accedervi. (Non dimenticare il con (scalmo) tavolo suggerimento!)

Modifica : ho pensato di una terza opzione:   È possibile creare una nuova tabella con le colonne appropriate, e quindi esportare i dati dalla tabella originale a quella nuova. Quando questo è fatto, è possibile eliminare la tabella originale e cambiare il nome del nuovo ad essere il vecchio. Per fare questo dovrete disattivare le dipendenze l'originale e impostare di nuovo su quello nuovo quando si è fatto, ma questo processo si riducono notevolmente la quantità di lavoro che dovete fare nelle ore fuori. Questo è lo stesso approccio che sql server utilizza quando si apportano modifiche colonna di ordinazione alle tabelle attraverso lo studio di gestione. Per questo approccio, vorrei fare l'inserto in blocchi per assicurarsi che non causare annullare stress sul sistema e impedire ad altri di accedervi. Poi sulle ore di riposo, è possibile eliminare l'originale, rinominare il secondo, e applicare le dipendenze ecc Avrai ancora un po 'fuori ore di lavoro, ma sarà minuscola rispetto a l'altro approccio.

Link utilizzando sp_rename .

Altri suggerimenti

L'unico modo per farlo "rapidamente" (*) che io conosca è tramite

  • creando una tabella "ombra" con il layout richiesto
  • aggiungendo un trigger alla tabella di origine in modo che qualsiasi operazione di inserimento/aggiornamento/eliminazione venga copiata nella tabella shadow (attenzione a catturare eventuali NULL che potrebbero apparire!)
  • copia tutti i dati dall'origine alla tabella shadow, potenzialmente in blocchi piccoli (assicurati di poter gestire i dati già copiati dai trigger), assicurati che i dati si adattino alla nuova struttura (ISNULL(?)! )
  • script tutte le dipendenze da/verso altre tabelle
  • al termine, eseguire le seguenti operazioni all'interno di una transazione esplicita:
    • ottieni un blocco tabella esclusivo sulla tabella sorgente e uno su shadowtable
    • eseguire gli script per eliminare le dipendenze nella tabella di origine
    • rinominare la tabella di origine in qualcos'altro (ad esempio il suffisso _old)
    • rinominare la tabella shadow con il nome originale della tabella di origine
    • eseguire gli script per creare nuovamente tutte le dipendenze

Potresti voler eseguire l'ultimo passaggio al di fuori della transazione poiché potrebbe richiedere un po' di tempo a seconda della quantità e della dimensione delle tabelle che fanno riferimento a questa tabella, i primi passaggi non richiederanno molto tempo

Come sempre, probabilmente è meglio eseguire prima un test su un server di prova =)

PS:per favore non essere tentato di ricreare gli FK con NOCHECK, li renderà inutili poiché l'ottimizzatore non si fiderà di loro né li prenderà in considerazione durante la creazione di un piano di query.

(*:dove si riduce rapidamente a:con il minor tempo di inattività possibile)

Ci scusiamo per l'abbattimento, ma:

  • Le eventuali modi per accelerarlo: No, se si desidera modificare la struttura della tabella stessa
  • o sto solo facendo bloccato durante la notte durante le ore? Sì, e questo è probabilmente per il meglio, come ha sottolineato @HLGEM
  • Anche questo potrebbe causare un blocco di tabella? Sì

Non direttamente rilevanti per voi (perché è di andare da NOT NULL NULL), ma interessante lettura su questo tema: http://beyondrelational.com/blogs/sankarreddy/archive/2011/04/ 05 / è-alter-tavolo-alter-column-non-nullo-a-zero-sempre-expensive.aspx

E infine un po 'di storia antica - su una questione equivalente in un forum, nel 2005, lo stesso suggerimento è stato fatto come @ Kevin offerto sopra - utilizzando un vincolo insteadof rendendo la colonna stessa non annullabile: http://www.sqlteam.com/Forums/topic.asp?TOPIC_ID=50671

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top