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

Indsnævring af datatyperne på en meget stor tabel

Først og fremmest, tak fordi du gjorde dette. Det er så oplagt en gevinst, som mange ikke ville se meget værdi i, men det vil være det værd :). Gør verden lidt sundere.

Angående IsActive at være boolsk. Mit gæt er, at du overvejer at gøre det til en BIT Mark. Det kan være vejen at gå, men nogle gange er det bedre at gå med TINYINT da der er mulighed for at udvide betydningen til mere end 2 tilstande. I så fald bliver det virkelig mere af StatusID . Normalt er der tale om noget, der forenklet starter som Aktivt / Inaktiv , men senere måske Slettet og/eller andre. Fra et størrelsesperspektiv, TINYINT er altid 1 byte. På den anden side, BIT er 1 byte i op til 8 BIT felter . Det betyder, en BIT feltet er 1 byte, 2 BIT felter er også en byte, og så videre op til 8 BIT felter gemt i en enkelt byte. Så der er ingen pladsbesparelse ved at vælge BIT over TINYINT når tabellen kun har 1 BIT Mark. Bare noget at overveje.

At lave et ALTER TABLE er lidt meget for et stort bord, som du så. En mulighed, selvom den ikke er god, er at tilføje en NOT NULL field--Number_1new --med en DEFAULT værdi (dette vil være øjeblikkelig på grund af standarden, i det mindste begyndende med SQL 2012), som ingen af ​​dem naturligt ville have (f.eks. 255), og derefter langsomt migrere værdierne i en loop, som i:

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

Og når det er gjort, så gør:

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

Selvfølgelig er det bedst at pakke det ind i en TRANSAKTION, og det indpakket i en TRY/CATCH. Når den relaterede kode er blevet opdateret, og alt er blevet testet, og dataene ser gode ud, kan du slippe Number_1old kolonne.

Den bedste måde, jeg har fundet, er dog at oprette en ny tabel, langsomt overføre dataene og derefter bytte tabeller og kode på samme tid. Jeg beskrev trinene i en artikel om SQL Server Central:Restructure 100 Million Row (eller mere) Tabeller på sekunder. SRSLY! (gratis tilmelding nødvendig). Bare hvis der er problemer med at komme til den artikel, er her de grundlæggende trin:

  1. Opret en ny tabel med den ideelle struktur--[tableNew]. Hvis du er på Enterprise Edition, kan du overveje at aktivere enten ROW- eller PAGE-komprimering, da de nogle gange kan hjælpe. Men gør venligst nogle undersøgelser først, da der er nogle situationer, hvor de har en negativ effekt. Der er dokumentation på MSDN, der hjælper dig med at finde ud af det, samt nogle værktøjer, der hjælper med at estimere potentielle besparelser. Men selvom du aktiverer komprimering, ville jeg ikke se den handling som en erstatning for det projekt, du laver her.
  2. Tilføj en trigger AFTER UPDATE, DELETE på [tabel] for at holde ændringer synkroniseret (men ingen grund til at bekymre dig om nye rækker)
  3. Opret et SQL Agent-job, der flytter over manglende rækker i batches. Gør dette i en løkke, der gør en INSERT INTO [tableNew] (Columns) SELECT TOP (n) Columns FROM [table] WHERE ?? ORDER BY ??
  4. WHERE og ORDER BY-klausulerne afhænger af situationen. De bør være gearet til at udnytte det klyngede indeks bedst muligt. Hvis det klyngede indeks for den nye tabel strukturelt er det samme som den gamle/nuværende tabel, så kan du ved starten af ​​hver løkke få MAX([id]) fra [tableNew] og bruge den til at få WHERE table.[id] > @MaxIdInTableNew ORDER BY table.[id] .
  5. Opret den nye tabel, udløs den aktuelle tabel og SQL Agent Job en uge eller deromkring, før du skal udføre den fulde cut-over. Den tidsramme kan ændre sig baseret på din situation, men sørg bare for at give dig selv masser af tid. Det er langt bedre for jobbet at afslutte migreringen af ​​rækker og kun have nogle få, der risler ind ad gangen, i modsætning til at være 100.000 genert af det fulde sæt, da udgivelsen skal begynde.
  6. Hvis planen er at migrere de andre relaterede tabeller (PK-referencerne for de to FK'er, som du vil omdanne til INT s), lav derefter disse felter her INT nu, og tilføj bare ikke FK'en, før de andre tabeller er migreret til at have INT-felter som deres PK'er. Du ønsker ikke at skulle genopbygge denne tabel igen bare for at foretage denne ændring for FK-felterne.
  7. Under cut-over (i en TRY/CATCH, selvfølgelig):
    1. BEGIN TRAN
    2. foretag en sidste rækketælling på begge tabeller for at sikre, at alt er flyttet over (det kan være en god ide at tjekke rækkerne før udgivelsen for at sikre, at udløseren foretog opdateringer og sletninger som forventet)
    3. omdøb den nuværende tabel til "gammel"
    4. omdøb den "nye" tabel for ikke at have den "nye"
    5. slip SQL Agent-jobbet (eller i det mindste deaktiver det)
    6. omdøb og afhængige objekter såsom begrænsninger osv.
    7. KOMMITTER


  1. Oprettelse af ny kolonne med rækker flyttet op i MySql

  2. Mine foretrukne PostgreSQL-udvidelser - del 1

  3. Tilføj en kolonne til en tabel i SQL

  4. Kan ikke kompilere SSIS-komponent; Manglende samling i Visual Studio 2008