Quale effetto avrà la riduzione della dimensione di una colonna varchar sul file del database?


15

Abbiamo un numero di tabelle nel nostro database che hanno VARCHAR(MAX)colonne in cui VARCHAR(500)sarà sufficiente una (o qualcosa di molto più piccolo di max). Ovviamente voglio ripulirli e portare le dimensioni a livelli più ragionevoli. Il 'come' per fare questo lo capisco: la mia domanda è: cosa farà l'alterazione di queste colonne alle pagine e agli esistenti su disco? (Ci sono molte informazioni là fuori su ciò che accade quando si coltiva una colonna, ma si riscontrano problemi nel trovare informazioni su ciò che accade quando si riduce una colonna.)

Alcune tabelle hanno un conteggio di righe molto ridotto, quindi non sono preoccupato per il costo della modifica, ma alcune sono piuttosto grandi e sono preoccupato che possano essere riorganizzate e causare molti blocchi / tempi di inattività. In termini pratici, voglio solo un modo per stimare una finestra di manutenzione. In generale, vorrei capire meglio come si comporta il motore di database in questo caso.

Grazie in anticipo!

MODIFICARE:

Ho 20 tavoli che sto guardando, anche se solo la metà ha un numero di righe maggiore di 1.000. Il più grande ha quasi un milione di file. Il peggior trasgressore è una tabella con 350.000 righe e quattro VARCHAR(MAX)colonne che possono ridursi al VARCHAR(500)livello.

Risposte:


12

Per prima cosa: quanti dati ci sono nella tabella? Numero di righe e dimensioni della tabella?

Secondo: è possibile eseguire il backup e ripristinare questa tabella su un server di prova ed eseguire l'istruzione alter per vedere l'impatto (supponendo che non sia impossibile a causa della tabella troppo grande per adattarsi a un sistema non di produzione)? Trovo sempre che i test nel mio ambiente siano più precisi dei consigli delle interwebs poiché ci sono diversi fattori che possono influenzare il risultato che potrebbero non essere forniti nella domanda semplicemente perché non sanno che tali fattori potrebbero influenzare il risultato.

Terzo: aumentare le dimensioni di un campo di lunghezza variabile è (supponendo che non si superi il limite di 8060 byte) una semplice operazione di metadati poiché nessun dato reale cambierebbe per tale operazione. MA, d'altra parte, ridurre le dimensioni di un campo a lunghezza variabile, anche a qualcosa che funzionerà più che ovviamente, non è una semplice modifica dei metadati perché SQL Server non lo sa, prima di scansionare tutte le righe , che la dimensione appena richiesta è valida.

Quindi: Sì, questo bloccherà la tabella per un periodo di tempo . Quanto tempo? Bene, ecco il test che ho appena fatto:

Ho avuto, da alcuni altri test, una tabella con un singolo INT NOT NULLcampo e 1 milione di righe. L'ho copiato in una nuova tabella allo scopo di eseguire questo test tramite:

SELECT *, CONVERT(NVARCHAR(MAX), NEWID()) AS [StringField]
INTO dbo.ResizeTest
FROM dbo.ClusteredUnique;

In questo modo stavo iniziando con uno scenario simile di avere un MAXcampo (mi sono appena reso conto che hai VARCHARe sto usando NVARCHAR, ma ciò non dovrebbe alterare il comportamento che sto vedendo) in cui potrei cambiare 500. E contiene dati che possono facilmente adattarsi a 500 caratteri. Ci sono voluti alcuni minuti.

Ho quindi eseguito:

ALTER TABLE dbo.ResizeTest ALTER COLUMN [StringField] NVARCHAR(500) NULL;

E ci sono voluti poco più di 11 minuti.

Ho rieseguito di nuovo il test, questa volta lasciando cadere il [ResizeTest]tavolo e cambiando entrambi NVARCHARper essere giusto VARCHAR, solo per essere super sicuro che sto confrontando le mele con qualcosa che almeno sembra una mela ;-).

La creazione della tabella iniziale ha richiesto 20 secondi mentre i ALTER TABLEminuti 2.

Quindi, in termini di stima dei tempi di inattività, è davvero difficile da fare in quanto si basa sulla velocità di I / O del disco, se è necessario eseguire o meno operazioni di crescita automatica sul file di dati e / o sul registro delle transazioni, ecc. è probabilmente una grande parte del motivo per cui il mio primo test ha richiesto 11 minuti per essere modificato e il secondo, pur VARCHARessendo la metà della dimensione dei NVARCHARdati, ha impiegato solo 2 minuti (ovvero i file sono stati pre-sviluppati a quel punto). Tuttavia, dovresti tenere a mente che il mio test è in esecuzione sul mio laptop, che non è il disco più veloce, ma era anche solo 1 milione di righe di 2 piccole colonne (circa 22 byte per riga).

E poiché hai chiesto cosa farà alle pagine dei dati, ecco la tua risposta. Ho fatto un sp_spaceuseddopo aver creato il tavolo, dopo aver fatto il ALTER COLUMN, e dopo averlo fatto ALTER TABLE dbo.ResizeTest REBUILD;. I risultati (i seguenti numeri si basano sul secondo test usando VARCHAR, non sul primo test usando NVARCHAR):

After initial table creation:        526,344 KB
After ALTER COLUMN VARCHAR(500):   1,031,688 KB  <--- !! Yikes!!
After ALTER REBUILD:                 526,472 KB

Se sei preoccupato di dover mantenere l'operazione nel minor tempo possibile, consulta un articolo che ho scritto per fare proprio questo: Ristruttura 100 milioni di righe (o più) tabelle in secondi. SRSLY! (è richiesta la registrazione gratuita).


2
Quindi ho copiato la tabella peggiore nella mia istanza locale (ovvero, disco più lento e 1/3 dei core). Ho modificato ALTERogni colonna in successione: ogni azione ha richiesto meno di un secondo. Quando furono terminati, il tavolo era raddoppiato in dimensioni, ma una volta che ho fatto un'operazione REBUILD(che era anche un'operazione di un secondo secondo), il tavolo è tornato alle sue dimensioni originali.
nateirvin,

@nateirvin È bello sentirlo. Probabilmente puoi velocizzare l' ALTER TABLEoperazione eseguendo tutti i campi in un colpo solo, separando ogni colonna con una virgola. Se la transazione è troppo grande, dividi la tabella in 2 istruzioni ALTER della metà delle colonne ciascuna. E a seconda della dimensione della tabella, puoi persino fare un REVISIONE tra ciascuna delle due istruzioni ALTER. Qualcosa con cui giocare. Inoltre, tieni presente che l'operazione richiederà probabilmente un blocco dello schema per la durata che bloccherà tutti gli accessi alla tabella.
Solomon Rutzky,

1
Ho fatto ciascuno ALTERseparatamente in modo da poter tenere traccia delle variazioni di dimensione tra ciascuno, ma sicuramente buono a sapersi. Grazie!
nateirvin,

1

Da quello che ho raccolto eseguendo l'istruzione alter non dovrebbe volerci molto a lungo finché il tavolo non è bloccato da un altro processo. Secondo gbn è solo una modifica dei metadati: /programming/7261909/is-it-bad-to-use-alter-table-to-resize-a-varchar-column-to-a-larger -taglia

Inoltre, per quanto riguarda il modo in cui viene archiviato, sembra che SQL Server abbia archiviato i dati varchar in una pagina 8k fino a quando non riempie un'intera pagina, che a questo punto li sostituisce con un puntatore e li memorizza come BLOB.

Suppongo che quando cambi la lunghezza, non troncerai alcun record. In tal caso, al massimo i dati che stai convertendo in varchar (500) dovrebbero essere lunghi al massimo 502 byte e non dovrebbero avere un puntatore.

Quindi, per farla breve, non molto dovrebbe cambiare fino a quando non si troncano i dati.


5
Questo è assolutamente errato. Non voglio sottovalutare perché lo hai effettivamente testato (il che è più di quello che fanno alcune persone, quindi grazie per averlo fatto), ma devi testarlo su larga scala. La risposta a cui ti sei collegato riguardava l'aumento delle dimensioni, non la riduzione. Sono due operazioni molto diverse.
Solomon Rutzky,
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.