Qual é o tamanho do valor “Nulo” no SQL Server

118

Eu tenho uma grande mesa com, digamos, 10 colunas. 4 deles permanecem nulos na maioria das vezes. Eu tenho uma consulta que faz o valor nulo leva qualquer tamanho ou nenhum tamanho em bytes. Li alguns artigos que alguns deles estão dizendo:

http://www.sql-server-citation.com/2009/12/common-mistakes-in-sql-server-part-4.html

Existe um equívoco de que, se tivermos os valores NULL em uma tabela, ela não ocupará espaço de armazenamento. O fato é que um valor NULL ocupa espaço - 2 bytes

SQL: usando valores NULL vs. valores padrão

Um NULLvalor em bancos de dados é um valor do sistema que ocupa um byte de armazenamento e indica que um valor não está presente em oposição a um espaço ou zero ou qualquer outro valor padrão.

Você pode me orientar quanto ao tamanho assumido pelo valor nulo.

Rocky Singh
fonte

Respostas:

146

Se o campo tiver largura fixa, o armazenamento de NULL ocupará o mesmo espaço que qualquer outro valor - a largura do campo.

Se o campo tiver largura variável, o valor NULL não ocupará espaço.

Além do espaço necessário para armazenar um valor nulo, também há uma sobrecarga por ter uma coluna anulável. Para cada linha, um bit é usado por coluna anulável para marcar se o valor dessa coluna é nulo ou não. Isso é verdade se a coluna é de comprimento fixo ou variável.


O motivo das discrepâncias que você observou nas informações de outras fontes:

  • O início do primeiro artigo é um pouco enganador. O artigo não está falando sobre o custo de armazenar um valor NULL, mas o custo de ter a capacidade de armazenar um NULL (ou seja, o custo de tornar uma coluna anulável). É verdade que custa algo em espaço de armazenamento tornar uma coluna anulável, mas uma vez que você tenha feito isso, leva menos espaço para armazenar um NULL do que para armazenar um valor (para colunas de largura variável).

  • O segundo link parece ser uma pergunta sobre o Microsoft Access. Não sei os detalhes de como o Access armazena NULLs, mas não ficaria surpreso se for diferente do SQL Server.

Mark Byers
fonte
1
@Mark "É verdade que custa algo em espaço de armazenamento tornar uma coluna anulável, mas uma vez que você tenha feito isso leva menos espaço para armazenar um NULL do que para armazenar um valor (para colunas de largura variável)". para dizer que leva 1 bit como o tamanho considerado na memória para tipos de dados variáveis.
Rocky Singh
13
A menor unidade endereçável de memória na maioria dos sistemas de computador é uma byte(normalmente 8 bits). Então, na realidade, a bitleva a byte. Ótima resposta, Mark: +1.
JohnB
20
No entanto, um segundo bit e um terceiro bit, e todo o caminho até um oitavo bit cabem no mesmo byte.
Matti Virkkunen
1
@Mark - Sim, parece muito mais claro. Desculpas pelo comentário que desapareceu. Eu pretendia revisá-lo, mas minha conexão com a Internet caiu entre a exclusão e o envio! Também depende um pouco (da seção de comentários aqui) "Para registro de heap e índice clusterizado, há sempre um bitmap NULL. Para índices não clusterizados, não haverá se todas as colunas no índice forem NOT NULL."
Martin Smith
2
@Martin Smith: Eu não sabia disso. Isso torna as coisas mais complicadas porque, se entendi corretamente, significa que tornar uma coluna anulável não aumenta o espaço de armazenamento necessário (porque o bitmap nulo está sempre presente), a menos que essa coluna também esteja em um índice e as outras colunas no índice não são anuláveis. Nesse caso, o índice agora deve incluir um bitmap nulo.
Mark Byers
30

O link a seguir afirma que se a coluna tem comprimento variável, ou seja varchar, NULLleva 0 bytes (mais 1 byte é usado para sinalizar se o valor é NULLou não):

O link acima, bem como o link abaixo, afirmam que para colunas de comprimento fixo, char(10)ou seja int, um valor de NULLocupa o comprimento da coluna (mais 1 byte para sinalizar se é NULLou não):

Exemplos:

  1. Se você definir um char(10)para NULL, ele ocupará 10 bytes (zerado)
  2. Um intleva 4 bytes (também zerados).
  3. Um varchar(1 million)conjunto para NULLleva 0 bytes (+ 2 bytes)

Nota: em uma ligeira tangente, o tamanho do armazenamento de varcharé o comprimento dos dados inseridos + 2 bytes.

JohnB
fonte
Um varchar armazenando um NULL não levaria 0 + 2 + 1 (sobrecarga NULL) bytes?
Akash
Deve ser + 1 bit para sinalizar NULL. @Akash: 2 bytes não devem ser necessários, pois o bitmap já sinaliza o valor como NULL (nenhuma informação seria adicionada).
Simo Kivistö
5

Deste link :

Cada linha possui um bitmap nulo para colunas que permitem nulos. Se a linha dessa coluna for nula, um bit no bitmap é 1, caso contrário, é 0.

Para tipos de dados de tamanho variável, o tamanho da conta é 0 bytes.

Para o tipo de dados de tamanho fixo, o tamanho da conta é o tamanho do tipo de dados padrão em bytes definido para o valor padrão (0 para números, '' para caracteres).

Kevin LaBranche
fonte
Você quer dizer que para tipos de dados como nvarchar (max) varchar (max) Null leva 0 bytes e para int, chars etc, leva o tamanho padrão para os valores padrão que eles têm?
Rocky Singh
4

Armazenar um valor NULL não ocupa nenhum espaço.

"O fato é que um valor NULL ocupa espaço - 2 bytes."

Isso é um equívoco - são 2 bytes por linha , e tenho certeza de que todas as linhas usam esses 2 bytes, independentemente de haver colunas anuláveis.

Um valor NULL em bancos de dados é um valor de sistema que ocupa um byte de armazenamento

Isso se refere a bancos de dados em geral, não especificamente ao SQL Server. O SQL Server não usa 1 byte para armazenar valores NULL.

Gabe
fonte