2009-09-22 26 views
21

Mam tabelę magazynową z 16 tonami danych. Mam w nim kilka kolumn całkowitoliczbowych. Musimy rzucić je do BIGINT dla każdego zapytania, które piszemy, ponieważ SUM jest zbyt duże, aby zmieścić się w INT.Zmiana INT do BigInt

Mamy teraz nową bazę danych w fazie rozwoju. Pomyśleliśmy więc, dlaczego nie zmienić wszystkich tych kolumn na BIGINT i mamy mniej powodów do zmartwień dla nowego zestawu zapytań.

Ponieważ dane są już załadowane, pomyślałem, że skorzystam z Management Studio i zmieni typ danych. Ale najpierw dostać ostrzeżenie:

Saving Definition Changes to tables with large amounts of data could take a considerable amount of time. While changes are being saved, table data will not be accessible.

Następnie pojawia się błąd:

Timeout expired. The timeout period elapsed prior to completion of the operation or the server is not responding.

Jak to obejść?

+45

16 ton danych - to dużo! – RedFilter

+0

Czy brałeś pod uwagę tabelę tymczasową, nową strukturę, wstawianie i zastępowanie? –

+2

@astander - to jest zasadniczo to, co zmienia schemat SSMS pod maską. – tvanfosson

Odpowiedz

43

Jeśli jeden lub więcej z tych kolumn nie mają ograniczeń wobec nich (jak klucz obcy, indeks, domyślny, reguła, etc), powinna być w stanie szybko zmienić każdy wykonując

ALTER TABLE monster ALTER COLUMN MyIntCol1 bigint

Zmiana Management Studio SQL rzadko jest najskuteczniejszy i preferuje tabele tymczasowe dla wszystkiego, co modyfikuje istniejącą kolumnę.

+1

Ciekawe, nie wiedziałem, że Studio Zarządzania było nieefektywne pod tym względem. – RedFilter

24

Nie wiem, czy to pomoże, ale spróbuj tego:

1 - create a new bigint column in the table 
2 - update that new column with the values from the int column 
3 - delete the int column 
4 - rename the bigint column 
+3

+1, to samo próbowałem napisać! –

+0

To samo tutaj pisałem to samo. (+1) Chciałbym dodać, że działa to również w przypadku replikacji. –

+1

Jedną rzeczą, na którą należy zwrócić uwagę przy tej technice, jest to, że zmieni kolejność kolumn. Chociaż to * powinno * być w porządku, możliwe, że gdzieś tam ktoś polega na tym porządku, aby być stabilnym, na przykład gdy wybierze * i wstawi do tabeli tymczasowej. –

2

rozszerzyć na OrbMan's odpowiedź:

  • dodać nowe kolumny u dołu listy kolumnowej (będzie go przyspieszyć dużo)
  • możesz zrobić swoje aktualizacje w partiach 10 000 wierszy lub w razie potrzeby
  • upewnij się, że jesteś w trybie pojedynczego użytkownika lub aplikacji, jeśli "OFF" więc nikt inny nie zmienia danych w tej tabeli

Ponadto, aby zobaczyć całą pracę, jaką ma studio Zarządzania po zmianie tabeli, kliknij ikonę paska narzędzi, która wygląda jak przewijanie z dyskietką. Spowoduje to wyświetlenie rzeczywistych poleceń SQL użytych do zmiany tabeli.

7

Myślę, że głównym błędem, na który możesz natknąć się, jest to, że GUI to limit czasu. Po zastosowaniu dużej zmiany przy użyciu opcji Modyfikuj wybór z SSMS upłynie limit czasu. Jeśli wykonasz to samo polecenie, generując skrypt zmian w SSMS, a następnie uruchamiając go jako proste zapytanie SQL, będzie on działał aż do ukończenia.

2

Jeśli dane źródłowe nigdy nie przekroczą limitu INT, wystarczy zrobić WIDOK, który uaktualnia kolumnę do BIGINT i zapytać o nią.

7

Ta technika sprawdziła się bardzo dobrze.

I wykonany:

use [Mytable] 
ALTER TABLE [dbo].[USER] ALTER COLUMN USER_ID bigint NOT NULL 

Spowodowało to błędem, ponieważ nie było ograniczenie na klucz:

Msg 5074, Level 16, State 1, Line 2 
The object 'PK_USER_USER_ID' is dependent on column 'USER_ID'. 
Msg 4922, Level 16, State 9, Line 2 
ALTER TABLE ALTER COLUMN USER_ID failed because one or more objects access this column. 

Nie zostać zahamowane w SQL Server Management Studio I kliknięciu prawym przyciskiem myszy na ograniczeniu PK_USER_USER_ID, a następnie wybrano "Klucz skryptu jako >> Upuść i utwórz w> Nowe okno edytora zapytań":

enter image description here

ten generowany ten skrypt:

USE [Database] 
GO 
/****** Object: Index [PK_USER_USER_ID] Script Date: 18/03/2014 13:05:38 ******/ 
ALTER TABLE [dbo].[USER] DROP CONSTRAINT [PK_USER_USER_ID] 
GO 

/****** Object: Index [PK_USER_USER_ID] Script Date: 18/03/2014 13:05:38 ******/ 
ALTER TABLE [dbo].[USER] ADD CONSTRAINT [PK_USER_USER_ID] PRIMARY KEY CLUSTERED 
(
[USER_ID] ASC 
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF,  ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] 
GO 

Potem wykonał pierwsza połowa tego skryptu, aby upuścić ograniczenie:

ALTER TABLE [dbo].[USER] DROP CONSTRAINT [PK_USER_USER_ID] 
GO 

teraz, że ograniczenie zniknął , oryginalna zmiana działała dobrze:

use [Mytable] 
ALTER TABLE [dbo].[USER] ALTER COLUMN USER_ID bigint NOT NULL 

Potem wykonał drugą połowę skryptu, aby dodać ograniczenie powrotem w:

ALTER TABLE [dbo].[USER] ADD CONSTRAINT [PK_USER_USER_ID] PRIMARY KEY CLUSTERED 
(
[USER_ID] ASC 
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF,  ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] 
GO