Encontrei várias fontes que afirmam ALTER TABLE ... DROP COLUMN é uma operação apenas de metadados.
Como isso pode ser? Os dados durante uma DROP COLUMN não precisam ser limpos dos índices não clusterizados subjacentes e do índice / heap clusterizado?
Além disso, por que o Microsoft Docs implica que é uma operação totalmente registrada?
As modificações feitas na tabela são registradas e totalmente recuperáveis. Alterações que afetam todas as linhas de tabelas grandes, como descartar uma coluna ou, em algumas edições do SQL Server, adicionar uma coluna NOT NULL com um valor padrão, podem levar muito tempo para concluir e gerar muitos registros de log . Execute essas instruções ALTER TABLE com o mesmo cuidado que qualquer instrução INSERT, UPDATE ou DELETE que afeta muitas linhas.
Como pergunta secundária: como o mecanismo controla as colunas descartadas se os dados não são removidos das páginas subjacentes?
fonte
Respostas:
Há certas circunstâncias em que largar uma coluna pode ser uma operação apenas de metadados. As definições de coluna para qualquer tabela não são incluídas em todas as páginas em que as linhas são armazenadas, as definições de coluna são armazenadas apenas nos metadados do banco de dados, incluindo sys.sysrowsets, sys.sysrscols, etc.
Ao eliminar uma coluna que não é referenciada por nenhum outro objeto, o mecanismo de armazenamento simplesmente marca a definição da coluna como não mais presente, excluindo os detalhes pertinentes de várias tabelas do sistema. A ação de excluir os metadados invalida o cache do procedimento, exigindo uma recompilação sempre que uma consulta fizer referência posteriormente a essa tabela. Como a recompilação retorna apenas colunas que existem atualmente na tabela, os detalhes da coluna eliminada nunca são solicitados; o mecanismo de armazenamento ignora os bytes armazenados em cada página dessa coluna, como se a coluna não existisse mais.
Quando uma operação DML subsequente ocorre na tabela, as páginas afetadas são reescritas sem os dados da coluna descartada. Se você recriar um índice em cluster ou um heap, todos os bytes da coluna descartada naturalmente não serão gravados de volta na página no disco. Isso efetivamente espalha a carga de soltar a coluna ao longo do tempo, tornando-a menos perceptível.
Há circunstâncias em que você não pode soltar uma coluna, como quando a coluna é incluída em um índice ou quando você criou manualmente um objeto de estatística para a coluna. Eu escrevi uma postagem de blog mostrando o erro que é apresentado ao tentar alterar uma coluna com um objeto de estatísticas criado manualmente. A mesma semântica se aplica ao descartar uma coluna - se a coluna for referenciada por qualquer outro objeto, ela não poderá ser simplesmente descartada. O objeto de referência deve ser alterado primeiro e, em seguida, a coluna pode ser descartada.
Isso é bastante fácil de mostrar, observando o conteúdo do log de transações depois de soltar uma coluna. O código abaixo cria uma tabela com uma única coluna de caracteres de 8.000 caracteres. Ele adiciona uma linha, a elimina e exibe o conteúdo do log de transações aplicável à operação de descarte. Os registros de log mostram modificações em várias tabelas do sistema em que as definições de tabela e coluna são armazenadas. Se os dados da coluna estivessem realmente sendo excluídos das páginas alocadas à tabela, você veria registros de log registrando os dados reais da página; não existem tais registros.
(A saída é grande demais para ser mostrada aqui e o dbfiddle.uk não permitirá que eu acesse fn_dblog)
O primeiro conjunto de saída mostra o log como resultado da instrução DDL descartando a coluna. O segundo conjunto de saída mostra o log após a execução da instrução DML onde atualizamos a
rid
coluna. No segundo conjunto de resultados, vemos registros de log indicando uma exclusão no dbo.DropColumnTest, seguido de uma inserção no dbo.DropColumnTest. Cada comprimento do registro de log é 8116, indicando que a página real foi atualizada.Como você pode ver na saída do
fn_dblog
comando no teste acima, toda a operação é totalmente registrada. Isso vale para a recuperação simples, bem como a recuperação completa. A terminologia "totalmente registrada" pode ser mal interpretada, pois a modificação dos dados não é registrada. Não é isso que acontece - a modificação é registrada e pode ser totalmente revertida. O log está simplesmente registrando apenas as páginas que foram tocadas e, como nenhuma das páginas de dados da tabela foi registrada pela operação DDL, aDROP COLUMN
reversão e qualquer reversão que possa ocorrer ocorrerão extremamente rapidamente, independentemente do tamanho da tabela.Para fins científicos , o código a seguir irá despejar as páginas de dados da tabela incluída no código acima, usando o
DBCC PAGE
estilo "3". O estilo "3" indica que queremos o cabeçalho da página mais uma interpretação detalhada por linha . O código usa um cursor para exibir os detalhes de todas as páginas da tabela; portanto, convém não executar isso em uma tabela grande.Observando a saída da primeira página da minha demonstração (após a queda da coluna, mas antes da atualização da coluna), vejo o seguinte:
Eu removi a maior parte do despejo de página bruta da saída mostrada acima por questões de concisão No final da saída, você verá isso na
rid
coluna:A última linha acima
rid = 1
,, retorna o nome da coluna e o valor atual armazenado na coluna na página.Em seguida, você verá o seguinte:
A saída mostra que o Slot 0 contém uma coluna excluída, em virtude do
DELETED
texto onde o nome da coluna normalmente estaria. O valor da coluna é retornado comoNULL
desde que a coluna foi excluída. No entanto, como você pode ver nos dados brutos, o valor de 8.000 caracteresREPLICATE('Z', 8000)
, para essa coluna ainda existe na página. Esta é uma amostra dessa parte da saída DBCC PAGE:fonte