Sqlserver
 sql >> Base de Dados >  >> RDS >> Sqlserver

Limitando os tipos de dados em uma tabela muito grande


Primeiramente, obrigado por fazer isso. É uma vitória tão óbvia que muitos não veriam muito valor, mas valerá a pena :). Tornando o mundo um pouco mais são.

Sobre IsActive sendo um booleano. Meu palpite é que você está pensando em torná-lo um BIT campo. Esse pode ser o caminho a seguir, mas às vezes é melhor usar TINYINT pois existe a possibilidade de expandir o significado para mais de 2 estados. Nesse caso, ele realmente se torna mais StatusID . Geralmente é o caso de algo começando de forma simplista como Ativo / Inativo , mas mais tarde talvez Excluído e/ou outros. De uma perspectiva de dimensionamento, TINYINT é sempre 1 byte. Por outro lado, BIT é de 1 byte para até 8 BIT campos . Ou seja, um BIT campo é 1 byte, 2 BIT campos também é um byte, e assim por diante até 8 BIT campos sendo armazenados em um único byte. Portanto, não há economia de espaço escolhendo BIT sobre TINYINT quando a tabela tem apenas 1 BIT campo. Apenas algo a considerar.

Fazer um ALTER TABLE é um pouco demais para uma mesa grande, como você viu. Uma opção, embora não seja ótima, é adicionar um NOT NULL campo--Number_1new --com um DEFAULT valor (isso será instantâneo devido ao padrão, pelo menos a partir do SQL 2012) que nenhum deles teria naturalmente (por exemplo, 255), e depois migrando lentamente os valores, em um loop, como em:
UPDATE TOP (5000) tab
SET tab.Number_1new = tab.Number_1
FROM [table] tab
WHERE tab.Number_1new = 255;

E quando isso for feito, então faça:
sp_rename 'table.Number_1', 'Number_1old', 'COLUMN';
sp_rename 'table.Number_1new', 'Number_1', 'COLUMN';

Claro, é melhor embrulhar isso em uma TRANSAÇÃO, e isso em um TRY / CATCH. Quando o código relacionado for atualizado e tudo tiver sido testado e os dados parecerem bons, você poderá descartar o Number_1old coluna.

No entanto, a melhor maneira que encontrei é criar uma nova tabela, fazer a transição lenta dos dados e depois trocar as tabelas e o código ao mesmo tempo. Eu detalhei as etapas em um artigo no SQL Server Central:Restructure 100 Million Row (ou mais) Tabelas em segundos. SRSLY! (inscrição gratuita obrigatória). Caso haja problemas para acessar esse artigo, aqui estão as etapas básicas:
  1. Crie uma nova tabela com a estrutura ideal--[tableNew]. Se você estiver no Enterprise Edition, considere habilitar a compactação ROW ou PAGE, pois às vezes elas podem ajudar. Mas, por favor, faça alguma pesquisa primeiro, pois há algumas situações em que eles têm um efeito negativo. Há documentação no MSDN para ajudá-lo a descobrir, bem como algumas ferramentas para ajudar a estimar a economia potencial. Mas mesmo que você ative a compactação, eu não veria essa ação como uma substituição do projeto que você está fazendo aqui.
  2. Adicione um acionador AFTER UPDATE, DELETE em [tabela] para manter as alterações sincronizadas (mas não precisa se preocupar com novas linhas)
  3. Crie um trabalho do SQL Agent que mova as linhas ausentes em lotes. Faça isso em um loop que faça um INSERT INTO [tableNew] (Columns) SELECT TOP (n) Columns FROM [table] WHERE ?? ORDER BY ??
  4. As cláusulas WHERE e ORDER BY dependem da situação. Eles devem ser orientados para fazer o melhor uso do índice clusterizado. Se o índice clusterizado da nova tabela for estruturalmente igual ao da tabela antiga/atual, no início de cada loop você poderá obter o MAX([id]) de [tableNew] e usá-lo para obter a tabela WHERE table.[id] > @MaxIdInTableNew ORDER BY table.[id] .
  5. Crie a nova tabela, dispare na tabela atual e execute o SQL Agent Job cerca de uma semana antes de precisar fazer a transferência completa. Esse prazo pode mudar com base na sua situação, mas certifique-se de dar a si mesmo bastante tempo. É muito melhor para o trabalho concluir a migração de linhas e ter apenas algumas por vez, em vez de ficar 100 mil antes do conjunto completo, já que o lançamento deve começar.
  6. Se o plano for migrar as outras tabelas relacionadas (as referências PK para os dois FKs que você deseja transformar em INT s), então faça esses campos aqui INT agora e apenas não adicione o FK até que essas outras tabelas sejam migradas para ter campos INT como seus PKs. Você não quer ter que reconstruir esta tabela novamente apenas para fazer essa alteração nos campos FK.
  7. Durante o cut-over (em um TRY / CATCH, é claro):
    1. INICIAR TRAN
    2. faça uma contagem final de linhas em ambas as tabelas para garantir que tudo seja movido (convém verificar a integridade das linhas antes do lançamento para garantir que o gatilho tenha feito as atualizações e exclusões conforme o esperado)
    3. renomeie a tabela atual para "antiga"
    4. renomeie a tabela "nova" para não ter a "nova"
    5. descarte o trabalho do SQL Agent (ou pelo menos desative-o)
    6. renomear e objetos dependentes, como restrições, etc
    7. COMPROMISSO