Sqlserver
 sql >> база данни >  >> RDS >> Sqlserver

Стесняване на типовете данни на много голяма таблица

Първо, благодаря ви, че правите това. Това е толкова очевидна победа, в която мнозина не биха видели голяма стойност, но ще си заслужава :). Прави света толкова малко по-разумен.

Относно IsActive като булево. Предполагам, че мислите да го направите BIT поле. Това може да е правилният начин, но понякога е по-добре да използвате TINYINT тъй като има възможност за разширяване на значението в повече от 2 състояния. В който случай наистина става повече от StatusID . Обикновено това е случай на нещо, което започва опростено като Активно / Неактивен , но по-късно може би Изтрит и/или други. От гледна точка на оразмеряването, TINYINT винаги е 1 байт. От друга страна, BIT е 1 байт за до 8 BIT полета . Което означава, един BIT полето е 1 байт, 2 BIT полетата също е един байт и така нататък до 8 BIT полетата се съхраняват в един байт. Така че няма спестяване на място, като изберете BIT над TINYINT когато таблицата има само 1 BIT поле. Просто нещо, което трябва да имате предвид.

Правенето на ALTER TABLE е малко за голяма маса, както видяхте. Една опция, макар и не добра, е да добавите NOT NULL поле--Number_1new --с DEFAULT стойност (това ще бъде мигновено поради стойността по подразбиране, поне започвайки с SQL 2012), която никой от тях естествено не би имал (напр. 255), и след това бавно мигриране на стойностите в цикъл, както в:

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

И когато това стане, направете:

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

Разбира се, най-добре е това да се увие в ТРАНЗАКЦИЯ, а това в TRY / CATCH. Когато свързаният код бъде актуализиран и всичко е тествано и данните изглеждат добре, тогава можете да премахнете Number_1old колона.

Въпреки това, най-добрият начин, който открих, е да създам нова таблица, бавно да прехвърлям данните, след което да разменям таблиците и кода едновременно. Подробно описах стъпките в статия за SQL Server Central:Restructure 100 Million Row (или повече) Таблици за секунди. SRSLY! (необходима е безплатна регистрация). Само в случай, че има проблеми с достигането до тази статия, ето основните стъпки:

  1. Създайте нова таблица с идеалната структура--[tableNew]. Ако сте на Enterprise Edition, помислете за активиране на компресия на ROW или PAGE, тъй като те понякога могат да помогнат. Но моля, първо направете някои изследвания, тъй като има ситуации, когато те имат отрицателен ефект. В MSDN има документация, която да ви помогне да го разберете, както и някои инструменти, които да ви помогнат да оцените потенциалното спестяване. Но дори и да активирате компресията, не бих видял това действие като заместващо проекта, който правите тук.
  2. Добавяне на тригер AFTER UPDATE, DELETE на [таблица], за да запазите промените в синхрон (но няма нужда да се притеснявате за нови редове)
  3. Създайте задание на SQL агент, което премества липсващите редове на партиди. Направете това в цикъл, който прави INSERT INTO [tableNew] (Columns) SELECT TOP (n) Columns FROM [table] WHERE ?? ORDER BY ??
  4. Клаузите WHERE и ORDER BY зависят от ситуацията. Те трябва да бъдат насочени към най-доброто използване на групирания индекс. Ако групираният индекс на новата таблица е структурно същият като старата/текущата таблица, тогава в началото на всеки цикъл можете да получите MAX([id]) от [tableNew] и да го използвате, за да получите WHERE table.[id] > @MaxIdInTableNew ORDER BY table.[id] .
  5. Създайте новата таблица, задействайте върху текущата таблица и SQL Agent Job около седмица, преди да трябва да извършите пълното прекъсване. Тази времева рамка може да се промени в зависимост от вашата ситуация, но просто се уверете, че сте си дали достатъчно време. Много по-добре е за работата да завърши мигрирането на редове и да има само няколко, които се процеждат наведнъж, вместо да ви липсват 100 000 от пълния набор, тъй като изданието трябва да започне.
  6. Ако планът е да мигрирате другите свързани таблици (PK препратките за двата FK, които искате да превърнете в INT s), след това направете тези полета тук INT сега и просто не добавяйте FK, докато тези други таблици не бъдат мигрирани, за да имат INT полета като техни PK. Не искате да се налага да изграждате тази таблица отново, само за да направите тази промяна за FK полетата.
  7. По време на прекъсването (в TRY / CATCH, разбира се):
    1. НАЧАЛО НА ТРАНС
    2. направете последно преброяване на редовете и на двете таблици, за да сте сигурни, че всичко е преместено (може да искате да проверите редовете преди пускането, за да сте сигурни, че тригерът е извършил актуализациите и изтриванията според очакванията)
    3. преименувайте текущата таблица на „стара“
    4. преименувайте „новата“ таблица, за да няма „нова“
    5. изтрийте заданието на SQL Agent (или поне го деактивирайте)
    6. преименуване и зависими обекти като ограничения и т.н.
    7. АНГАЖИРАНЕ


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Динамични t-sql кавички в низ

  2. C# Enum, използвайки стойности в таблицата на Sql сървъра

  3. Актуализиране на пощенски профил на база данни (SSMS)

  4. Обхват на променливата на SQL Server в съхранена процедура

  5. Вземете всичко след и преди определен знак в SQL Server