Tabelas idênticas, colunas idênticas, registros idênticos, mas por que tamanhos de registro diferentes?
USE [test]
GO
CREATE TABLE [dbo].[mybit](
[col1] [bit] NOT NULL,
[col2] [bit] NOT NULL,
[col3] [bit] NOT NULL,
[col4] [bit] NOT NULL,
[col5] [bit] NOT NULL,
[col6] [bit] NOT NULL,
[col7] [bit] NOT NULL,
[col8] [bit] NOT NULL,
[col9] [bit] NULL
)
GO
INSERT INTO [dbo].[mybit]
VALUES (1,1,1,1,1,1,1,1,NULL)
GO 2
DBCC IND(test, mybit, -1);
GO
DBCC TRACEON(3604);
DBCC PAGE(test, 1, '#pagenumber', 1);
Ambos os registros têm 10 bytes de tamanho.
CREATE TABLE [dbo].[mybit2](
[col1] [bit] NOT NULL,
[col2] [bit] NOT NULL,
[col3] [bit] NOT NULL,
[col4] [bit] NOT NULL,
[col5] [bit] NOT NULL,
[col6] [bit] NOT NULL,
[col7] [bit] NOT NULL,
[col8] [bit] NOT NULL,
)
GO
INSERT INTO [dbo].[mybit2]
VALUES (1,1,1,1,1,1,1,1)
GO
ALTER TABLE [dbo].[mybit2] ADD [col9] [bit] NULL
GO
INSERT INTO [dbo].[mybit2]
VALUES (1,1,1,1,1,1,1,1, NULL)
GO
DBCC IND(test, mybit2, -1);
GO
DBCC TRACEON(3604);
DBCC PAGE(test, 1, '#pagenumber', 1);
Um registro tem 9 bytes de tamanho e outro tem 10.
Thomas Cleberg está correto.
A primeira linha que você insere
bit2
aparece na página DBCC comoIsso se decompõe da seguinte forma
(Se você está se perguntando por que existe um byte "sobressalente". Isso é explicado aqui . É para permitir que a linha seja substituída por um ponteiro de encaminhamento, caso seja necessário. O valor dele é arbitrário. Para mim foi
0x63
. Para você parece que foi0x00
)Depois de alterar a tabela e adicionar uma nova coluna com um
NULL
valor (ou um valor padrão constante de tempo de execução no SQL Server 2012+ Enterprise Edition), essa é uma alteração apenas de metadados. O SQL Server não atualiza as linhas existentes. Ele pode deduzir da contagem de colunas armazenada na linha que o valor paracol9
deve serNULL
para essa linha. A alteração será gravada na próxima vez que a linha for atualizada.As linhas inseridas recentemente serão escritas por completo. Dois bytes extras são necessários porque o único byte na seção de dados fixos está cheio de valores para as colunas de bits 1-8, portanto, um byte adicional é necessário para as colunas de bits 9 a 16. Além disso, o bitmap nulo também cresce em um byte. No entanto, não há necessidade de reter esse byte "sobressalente" para manter o tamanho da linha em um nível mínimo, portanto, o efeito líquido é um aumento de um byte.
Não é inteiramente verdade. A princípio, eles eram diferentes e a linha 1 foi adicionada
[mybit2]
quando eles eram diferentes. Sua segunda imagem, aDBCC PAGE
saída para[mybit2]
, indica claramente esse fato.Simplificando: você alterou a definição da tabela e não a reconstruiu . Algumas operações podem ser realizadas instantaneamente (também conhecidas como "online"), pois não há necessidade urgente de refletir imediatamente essas alterações nas linhas existentes:
Recuperar espaço após adicionar a opção SPARSE (às vezes) a um campo NULLable (a partir do SQL Server 2008)
[A página do MSDN para ALTER TABLE tem notas sobre: adicionar colunas NOT NULL com um DEFAULT, descartar colunas e adicionar a
SPARSE
opção. ]Nesses casos, você precisa reconstruir o Clustered Index (ou a tabela se for um heap), que é quando o SQL Server irá passar por cada registro e fazer os ajustes necessários. Faça o seguinte para vê-lo:
[mybit2]
mesa[mybit2]
com 8 campos, adicione uma linha e, em seguida, ALTER para adicionar o 9º campo e adicione uma linhaDBCC PAGE
apenas para garantir que o registro 1 tenha 9 bytes e o registro 2 tenha 10 bytesALTER TABLE dbo.mybit2 REBUILD;
DBCC IND(0, mybit2, -1); -- 0 = current DB
já que a reconstrução provavelmente moveu o conteúdo para outra páginaDBCC PAGE
novamente (com o novo PagePID!) e você verá que o "tamanho do registro" para ambos os registros agora é de 10 bytesAinda mais divertido:
ALTER TABLE dbo.mybit2 DROP COLUMN col5;
executivo:
Ambos os registros ainda têm um "Tamanho do registro" de 10 bytes, mas o que era
col5
agora é exibido comoDROPPED
.ALTER TABLE dbo.mybit2 REBUILD;
DBCC IND(0, mybit2, -1); -- 0 = current DB
já que a reconstrução provavelmente moveu o conteúdo para outra páginaexecutivo:
Ambos os registros agora têm um "Tamanho do registro" de 9 bytes e não há mais espaços reservados para
col5
isso, comoDROPPED
naField
colunaSua segunda tabela tem 8 colunas, a primeira tem 9. Como o tipo de dados é "Bit", isso explica exatamente a diferença.
Talvez eu esteja perdendo alguma coisa, mas você percebe que começa com 8 colunas, faz uma inserção, depois altera a tabela e adiciona uma 9ª coluna e depois faz outra inserção. Claro que o tamanho vai ser diferente quando a primeira inserção foi em 8 colunas e a segunda em 9 colunas.