Jak podzielić istniejącą niepodzieloną na partycje tabelę

22

Mam istniejącą tabelę z danymi:

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

Muszę zmienić tę tabelę, aby podzielić ją na partycje w następujący sposób:

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

Jak mogę to osiągnąć bez upuszczania i odtwarzania tabeli?

343
źródło

Odpowiedzi:

23

Aby podzielić tabelę na partycje, możesz wykonać poniższe krótkie kroki:

  • najpierw utwórz funkcję partycji i schemat partycji
  • Następnie możesz podzielić tabelę na partycje.
  • JEŻELI twoja tabela ma indeks klastrowany, musisz upuścić i ponownie utworzyć go na właściwej partycji lub użyć DROP_EXISTINGklauzuli, aby ponownie utworzyć indeks klastrowany.
  • Jeśli twoja tabela nie ma indeksu klastrowego, możesz po prostu utworzyć go na właściwej partycji, korzystając ze schematu partycji.
  • Również wersja Enterprise ma elastyczność korzystania z ONLINE=ONopcji instrukcji CREATE INDEX, aby zminimalizować wszelkie przestoje aplikacji. Pamiętaj, że podczas odbudowywania indeksu zobaczysz spadek wydajności przy użyciu opcji ONLINE.

Aby zautomatyzować partycjonowanie, możesz użyć narzędzia SQL Server Partition Management lub SQL Server Partitioned Table Framework dostępnego również na codeplex.

Niektóre dobre zasoby:

Kin Shah
źródło
53

Nie określasz, czy tabela ma indeks klastrowany, czy nie, więc przejrzyjmy wszystkie opcje.

Użyję tej przykładowej funkcji partycji, schematu partycji i tabeli:

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. Twoja tabela ma klastrowany indeks, który nie został utworzony przez ograniczenie.

To najłatwiejszy przypadek. Możesz po prostu użyć CREATE INDEXinstrukcji z DROP_EXISTINGklauzulą, aby przenieść tabelę do schematu partycji.

Załóżmy na przykład, że ten indeks klastrowy został utworzony:

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

Aby podzielić tę tabelę, indeks klastrowany zawiera kolumnę partycji (w naszym przypadku pt) jako część klucza. Ta instrukcja zmienia indeks klastrowy, tak aby obejmował kolumnę partycji i dzieli ją na partycje w tym samym czasie:

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

DROP_ExistingKlauzula automatycznie usuwa istniejący indeks przed utworzeniem nowego. Jest to preferowane DROP INDEXzamiast osobnego, ponieważ powoduje, że indeksy nieklastrowane są odbudowywane tylko raz.

2. Tabela ma indeks klastrowy będący częścią ograniczenia PRIMARY KEYlub UNIQUEzawierający kolumnę partycji jako część klucza

Ten jest wciąż łatwy i bardzo podobny do poprzedniego.

Załóżmy, że to PRIMARY KEYograniczenie zostało utworzone w tabeli:

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

Teraz możesz po prostu uruchomić ten sam skrypt ponownego tworzenia, którego użyliśmy w 1:

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

3. Tabela ma indeks klastrowy, który nie zawiera kolumny partycji, ale został utworzony jako część ograniczenia PRIMARY KEYlubUNIQUE

Pech. Po fakcie nie można zmienić definicji ograniczenia PRIMARY KEYani UNIQUEograniczenia. Jedyną opcją jest usunięcie ograniczenia, a następnie albo odtworzenie go, łącznie z kolumną partycji, albo utworzenie indeksu klastrowego niezależnie od ograniczenia zawierającego kolumnę partycji. W drugim przypadku możesz odtworzyć ograniczenie NONCLUSTEREDbez uwzględnienia kolumny partycji. Ponieważ teraz to ograniczenie nie jest wyrównane (co oznacza, że ​​jego indeks pomocniczy nie jest podzielony na partycje), musisz określić, gdzie umieścić go na dysku.

Załóżmy, że tabela miała taki klucz podstawowy:

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

Aby podzielić tę tabelę na partycje, musisz najpierw usunąć ograniczenie:

ALTER TABLE dbo.pt DROP CONSTRAINT ptc;

Następnie musisz utworzyć indeks klastrowany podzielony na partycje:

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

Jeśli zdecydujesz się odtworzyć PRIMARY KEYwiązanie niezrównane, możesz to zrobić w następujący sposób:

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

4. Twoja tabela nie ma indeksu klastrowego

W takim przypadku w większości przypadków zaleca się utworzenie indeksu klastrowego w celu ustanowienia partycjonowania. Możesz do tego użyć wcześniej utworzonej instrukcji tworzenia indeksu:

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

Jeśli jednak masz dobry powód, aby nie tworzyć indeksu klastrowego, możesz zastosować następujące dwustopniowe podejście. Niestety nie ma bezpośredniego sposobu na dokonanie tej zmiany.

Załóżmy, że twoja tabela nie ma indeksu klastrowego. Aby podzielić tabelę na partycje, musisz najpierw utworzyć CLUSTERED UNIQUEograniczenie. (Możesz również użyć CLUSTERED PRIMARY KEYograniczenia). Jeśli masz unikalną kombinację kolumn, jest to prosty krok:

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

Po utworzeniu ograniczenia możesz je upuścić ponownie i jednocześnie „przenieść” tabelę do nowego schematu partycji:

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

Jeśli nie masz unikalnej kombinacji kolumn, nie masz szczęścia. W takim przypadku jedyną opcją jest dodanie nowej kolumny i wypełnienie jej unikalnymi wartościami. Jeśli stół jest dość mały, możesz zrobić coś takiego:

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

Jednak zajmie to wyłączną blokadę tabeli, dopóki wszystkie wiersze nie zostaną wycenione. W zależności od wielkości stołu może to trwać dość długo. Po utworzeniu tej kolumny wykonaj dwa powyższe kroki, aby najpierw utworzyć UNIQUEograniczenie, a następnie natychmiast je upuścić. Następnie możesz ponownie upuścić kolumnę. Wszystkie te kroki są dość inwazyjne, więc prawdopodobnie lepiej jest po prostu utworzyć indeks klastrowany na stole. To wcale nie musi być wyjątkowe.


Jeśli masz wersję Enterprise, możesz użyć WITH(ONLINE=ON)klauzuli na większości powyższych stwierdzeń. Dzięki temu Twój stół będzie dostępny dla innych połączeń. Jednak w tym czasie będzie miało to wpływ na wydajność.

Sebastian Meine
źródło
1
Doskonale, Sabastianin! Po prostu doskonale! Aby dodać do powyższego punktu 3 ... jeśli chcesz używać SWITCH in lub out, wszystkie indeksy muszą być wyrównane. Wykonanie nieklastrowanego, nieprzystosowanego PK nie pozwoli ci wykonać PRZEŁĄCZNIKA, chyba że najpierw wykonasz kroki, aby upuścić indeks, wykonaj PRZEŁĄCZNIK (niezależnie od tego, w jakim kierunku on będzie) i odbuduj indeks. To bardzo często jest jeszcze szybsze niż robienie ekwiwalentu z usuwaniem i, oczywiście, jeśli nie musisz używać SWITCH, nie będzie problemu.
Jeff Moden