Come partizionare una tabella esistente non partizionata


22

Ho una tabella esistente con dati:

dbo.Test (col1,col2,col3....) ON [PRIMARY]

Ho bisogno di cambiare questa tabella per essere partizionato in questo modo:

dbo.Test(col1,col2,col3....) ON Ps_Date(Col2)

Come posso raggiungere questo obiettivo senza abbandonare e ricreare il tavolo?

Risposte:


23

Per partizionare una tabella, puoi seguire i seguenti brevi passaggi:

  • creare prima una funzione di partizione e uno schema di partizione
  • Dopodiché puoi partizionare una tabella.
  • Se la tabella ha un indice cluster, è necessario rilasciarlo e ricrearlo sulla partizione corretta oppure è possibile utilizzare la DROP_EXISTINGclausola per ricreare l'indice cluster.
  • Se la tua tabella non ha un indice cluster, puoi semplicemente crearne uno sulla partizione giusta usando lo schema di partizione.
  • Anche Enterprise Edition ha la flessibilità di utilizzare l' ONLINE=ONopzione dell'istruzione CREATE INDEX per ridurre al minimo i tempi di inattività per l'applicazione. Noterai che vedrai un peggioramento delle prestazioni mentre l'indice viene ricostruito usando l'opzione ONLINE.

Per automatizzare il partizionamento, è possibile utilizzare l' utilità di gestione delle partizioni di SQL Server o SQL Server Partitioned Table Framework disponibile anche su codeplex.

Alcune buone risorse:


53

Non specifichi se la tua tabella ha un indice cluster o no, quindi esaminiamo tutte le opzioni.

Ho intenzione di utilizzare questa funzione di partizione di esempio, schema di partizione e tabella:

CREATE PARTITION FUNCTION pf1(INT) AS RANGE LEFT FOR VALUES(10,20,30,40);
GO
CREATE PARTITION SCHEME ps1 AS PARTITION pf1 ALL TO ([PRIMARY])
GO
CREATE TABLE dbo.pt(pc INT NOT NULL, id INT NOT NULL) ON [PRIMARY];
GO

1. La tabella ha un indice cluster che non è stato creato da un vincolo.

Questo è il caso più semplice. Puoi semplicemente usare l' CREATE INDEXistruzione con la DROP_EXISTINGclausola per spostare la tabella nello schema di partizione.

Supponiamo per l'esempio che questo indice cluster sia stato creato:

CREATE UNIQUE CLUSTERED INDEX ptc ON dbo.pt(Id) ON [PRIMARY];

Per partizionare questa tabella, l'indice cluster ha incluso la colonna di partizione (pt nel nostro caso) come parte della chiave. Questa istruzione modifica l'indice cluster per includere la colonna di partizione e le partiziona contemporaneamente:

CREATE UNIQUE CLUSTERED INDEX ptc ON dbo.pt(pc, Id) WITH(DROP_EXISTING = ON)ON ps1(pc) ;

La DROP_Existingclausola rimuove automaticamente l'indice esistente prima di crearne uno nuovo. Questo è preferito su un separato DROP INDEXin quanto provoca la ricostruzione degli indici non cluster solo una volta.

2. La tabella ha un indice cluster che fa parte di un vincolo PRIMARY KEYo UNIQUEe contiene la colonna della partizione come parte della chiave

Questo è ancora facile e molto simile al precedente.

Supponiamo che questo PRIMARY KEYvincolo sia stato creato nella tabella:

ALTER TABLE dbo.pt ADD CONSTRAINT ptc PRIMARY KEY CLUSTERED (pc, Id) ON [PRIMARY];

Ora puoi semplicemente eseguire lo stesso script di ricostruzione che abbiamo usato in 1:

CREATE UNIQUE CLUSTERED INDEX ptc ON dbo.pt(pc, Id) WITH(DROP_EXISTING = ON)ON ps1(pc) ;

3. La tabella ha un indice cluster che non include la colonna di partizione, ma è stato creato come parte di una PRIMARY KEYo di UNIQUEvincolo

Buona fortuna Non è possibile modificare la definizione di a PRIMARY KEYo UNIQUEvincolo dopo il fatto. L'unica opzione è eliminare il vincolo e quindi ricrearlo includendo la colonna della partizione o creare un indice cluster indipendente dal vincolo che include la colonna della partizione. Nel secondo caso è possibile ricreare il vincolo NONCLUSTEREDsenza includere la colonna di partizione. Perché ora questo vincolo non è allineato (il che significa che il suo indice di supporto non è partizionato) è necessario specificare dove posizionarlo sul disco.

Supponiamo che la tabella avesse una chiave primaria come questa:

ALTER TABLE dbo.pt ADD CONSTRAINT ptc PRIMARY KEY CLUSTERED (Id) ON [PRIMARY];

Per partizionare questa tabella devi prima eliminare il vincolo:

ALTER TABLE dbo.pt DROP CONSTRAINT ptc;

Quindi è necessario creare l'indice cluster partizionato:

CREATE UNIQUE CLUSTERED INDEX ptci ON dbo.pt(pc, Id) ON ps1(pc) ;

Se si sceglie di ricreare il PRIMARY KEYvincolo non allineato, è possibile farlo in questo modo:

ALTER TABLE dbo.pt ADD CONSTRAINT ptc PRIMARY KEY NONCLUSTERED (Id) ON [PRIMARY];

4. La tua tabella non ha un indice cluster

In questo caso, nella maggior parte dei casi, si consiglia di creare un indice cluster per stabilire il partizionamento. È possibile utilizzare l'istruzione di indice di creazione vista precedentemente visualizzata per quello:

CREATE UNIQUE CLUSTERED INDEX ptci ON dbo.pt(pc, Id) ON ps1(pc) ;

Tuttavia, se si ha una buona ragione per non creare un indice cluster, è possibile cavarsela con il seguente approccio in due passaggi. Purtroppo non esiste un modo diretto per apportare questo cambiamento.

Supponiamo che la tua tabella non abbia un indice cluster. Per partizionare la tabella devi prima creare un CLUSTERED UNIQUEvincolo. (Potresti anche usare un CLUSTERED PRIMARY KEYvincolo). Se hai una combinazione di colonne unica che è un semplice passaggio:

ALTER TABLE dbo.pt ADD CONSTRAINT ptc UNIQUE CLUSTERED(pc,id);

Dopo aver creato il vincolo, è possibile rilasciarlo di nuovo e "spostare" contemporaneamente la tabella nel nuovo schema di partizione:

ALTER TABLE dbo.pt DROP CONSTRAINT ptc WITH(MOVE TO ps1(pc));

Se non hai una combinazione di colonne unica, sei sfortunato. In questo caso, l'unica opzione è quella di aggiungere una nuova colonna e riempirla con valori univoci. Se la tabella è abbastanza piccola, potresti fare qualcosa del genere:

ALTER TABLE dbo.pt ADD tmp_id INT IDENTITY(1,1);

Tuttavia, ciò richiederà un blocco tabella esclusivo fino a quando tutte le righe vengono valutate. A seconda delle dimensioni della tabella, ciò può durare per un po '. Dopo aver creato quella colonna, seguire i due passaggi precedenti per creare prima il UNIQUEvincolo e quindi rilasciarlo immediatamente. Successivamente puoi anche rilasciare di nuovo la colonna. Tutti questi passaggi sono abbastanza invadenti, quindi probabilmente è meglio creare un indice cluster sulla tabella. Questo non deve nemmeno essere unico.


Se si dispone di Enterprise Edition, è possibile utilizzare la WITH(ONLINE=ON)clausola sulla maggior parte delle dichiarazioni precedenti. Ciò manterrà la tua tabella disponibile per altre connessioni. Tuttavia, ci sarà un impatto sulle prestazioni durante quel periodo.


1
Eccellente Sabastiano! Semplicemente eccellente! Solo per aggiungere al n. 3 sopra ... se si desidera utilizzare SWITCH in o out, tutti gli indici devono essere allineati. Realizzare un PK non cluster, non allineato non ti permetterà di fare un INTERRUTTORE a meno che tu non segua i passi per rilasciare prima l'indice, esegui l'INTERRUTTORE (qualunque direzione si trovi) e ricostruisci l'indice. Molto spesso è ancora più veloce che fare l'equivalente con le eliminazioni e, naturalmente, se non è necessario utilizzare SWITCH, non sarà un problema.
Jeff Moden,
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.