{"id":1323,"date":"2012-02-29T08:09:19","date_gmt":"2012-02-29T10:09:19","guid":{"rendered":"http:\/\/fabriciolima.net\/blog\/?p=1323"},"modified":"2016-07-24T09:50:52","modified_gmt":"2016-07-24T12:50:52","slug":"colunas-com-valores-null-ocupam-espaco-em-disco-mito","status":"publish","type":"post","link":"https:\/\/fabriciolima.net\/blog\/2012\/02\/29\/colunas-com-valores-null-ocupam-espaco-em-disco-mito\/","title":{"rendered":"Colunas com valores NULL ocupam espa\u00e7o em disco? Mito?"},"content":{"rendered":"<p>Ol\u00e1 Pessoal,<\/p>\n<p>Muitos de voc\u00eas j\u00e1 devem ter recebido a seguinte solicita\u00e7\u00e3o: &#8220;<strong>Favor criar uma coluna nova na tabela X (80 milh\u00f5es de linhas). Como os valores existentes ser\u00e3o NULLs, esse campo n\u00e3o ocupar\u00e1 espa\u00e7o em disco e n\u00e3o teremos nenhum impacto nessa tabela<\/strong>&#8220;.<\/p>\n<p>Entretanto, n\u00e3o \u00e9 exatamente isso que acontece!<\/p>\n<p>Tipos de dados que possuem um tamanho fixo ocupam espa\u00e7o em disco mesmo sendo NULL. Ex: Int, bigint, char, datetime e etc..<\/p>\n<p>Tipos de dados que possuem um tamanho vari\u00e1vel, n\u00e3o ocupam espa\u00e7o em disco quando NULL . Ex: Varchar(100). Com exce\u00e7\u00e3o dos 2 bytes que o tipo varchar j\u00e1 ocupa inicialmente.<\/p>\n<p>Voc\u00ea pode verificar isso criando duas tabelas com as mesmas colunas, mas inserindo somente valores NULLs em uma tabela e somente valores n\u00e3o NULLs em outra tabela:<\/p>\n<p>create table Teste_NULL(<br \/>\nId int identity(1,1),<br \/>\nTesteInt int NULL,<br \/>\nTesteData datetime,<br \/>\nTesteChar char(10),<br \/>\nTesteNumeric numeric(15,2),<br \/>\nconstraint PK_Teste_NULL primary key (Id))<\/p>\n<p>create table Teste_NOTNULL(<br \/>\nId int identity(1,1),<br \/>\nTesteInt int NOT NULL,<br \/>\nTesteData datetime NOT NULL,<br \/>\nTesteChar char(10) NOT NULL,<br \/>\nTesteNumeric numeric(15,2) NOT NULL,<br \/>\nconstraint PK_Teste_NOTNULL primary key(Id))<\/p>\n<p>SET NOCOUNT ON<br \/>\n&#8212; Fiz um loop para funcionar em qualquer vers\u00e3o do SQL Server<br \/>\ndeclare @loop int<br \/>\nset @loop= 1<br \/>\nwhile @loop&lt;= 20000<br \/>\nbegin<br \/>\ninsert into Teste_NULL<br \/>\nselect null,null,null,null<\/p>\n<p>insert into Teste_NOTNULL<br \/>\nselect @loop,getdate(),&#8217;1234567890&#8242;, 9999999999999.99<br \/>\nset @loop= @loop + 1<br \/>\nend<\/p>\n<p>exec sp_spaceused Teste_NULL<br \/>\nexec sp_spaceused Teste_NOTNULL<\/p>\n<p>Essa query acima gera o resultado:<\/p>\n<p style=\"text-align: center;\"><a href=\"https:\/\/www.fabriciolima.net\/blog\/wp-content\/uploads\/2012\/02\/spaceusedTabelas.png\" target=\"_blank\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-1324\" title=\"spaceusedTabelas\" src=\"https:\/\/www.fabriciolima.net\/blog\/wp-content\/uploads\/2012\/02\/spaceusedTabelas.png\" alt=\"\" width=\"435\" height=\"189\" srcset=\"https:\/\/fabriciolima.net\/blog\/wp-content\/uploads\/2012\/02\/spaceusedTabelas.png 402w, https:\/\/fabriciolima.net\/blog\/wp-content\/uploads\/2012\/02\/spaceusedTabelas-300x131.png 300w, https:\/\/fabriciolima.net\/blog\/wp-content\/uploads\/2012\/02\/spaceusedTabelas-100x44.png 100w, https:\/\/fabriciolima.net\/blog\/wp-content\/uploads\/2012\/02\/spaceusedTabelas-275x120.png 275w, https:\/\/fabriciolima.net\/blog\/wp-content\/uploads\/2012\/02\/spaceusedTabelas-20x9.png 20w\" sizes=\"auto, (max-width: 435px) 100vw, 435px\" \/><\/a><\/p>\n<p>Conforme pode ser visto, as duas tabelas possuem 20.000 linhas e ocupam o mesmo espa\u00e7o em disco. Logo, est\u00e1 provado que colunas com valores NULL tamb\u00e9m ocupam espa\u00e7o em disco.<\/p>\n<p>Entretanto, ao adicionarmos um campo em uma tabela existente, o sql server n\u00e3o aumenta o espa\u00e7o em disco ocupado por essa tabela.<\/p>\n<p>Visualizando:<\/p>\n<p>ALTER TABLE Teste_NULL<br \/>\nAdd Novacoluna datetime NULL<\/p>\n<p>Conferindo o tamanho da tabela Teste_NULL, podemos verificar que o mesmo n\u00e3o foi alterado:<\/p>\n<p><a href=\"https:\/\/www.fabriciolima.net\/blog\/wp-content\/uploads\/2012\/02\/spaceusedTabelas2.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-1325\" title=\"spaceusedTabelas2\" src=\"https:\/\/www.fabriciolima.net\/blog\/wp-content\/uploads\/2012\/02\/spaceusedTabelas2.png\" alt=\"\" width=\"378\" height=\"104\" srcset=\"https:\/\/fabriciolima.net\/blog\/wp-content\/uploads\/2012\/02\/spaceusedTabelas2.png 378w, https:\/\/fabriciolima.net\/blog\/wp-content\/uploads\/2012\/02\/spaceusedTabelas2-300x83.png 300w, https:\/\/fabriciolima.net\/blog\/wp-content\/uploads\/2012\/02\/spaceusedTabelas2-100x28.png 100w, https:\/\/fabriciolima.net\/blog\/wp-content\/uploads\/2012\/02\/spaceusedTabelas2-275x76.png 275w, https:\/\/fabriciolima.net\/blog\/wp-content\/uploads\/2012\/02\/spaceusedTabelas2-20x6.png 20w\" sizes=\"auto, (max-width: 378px) 100vw, 378px\" \/><\/a><\/p>\n<p>Ent\u00e3o isso \u00e9 uma exce\u00e7\u00e3o e o SQL Server n\u00e3o ocupa espa\u00e7o em disco quando criamos esse campo???<\/p>\n<p>N\u00e3o \u00e9 bem assim. O SQL Server cria o seu novo campo apenas nos metadados, mas ele n\u00e3o percorre todas as p\u00e1ginas de dados alterando o tamanho das linhas da tabela para a inclus\u00e3o desse novo campo. Como n\u00f3s criamos campos no meio do dia (em zero segundos), essa opera\u00e7\u00e3o seria muito custosa de ser realizada.<\/p>\n<p>Contudo, ao realizarmos um REBUILD do \u00edndice clustered dessa tabela, o SQL Server recria as p\u00e1ginas de dados dessa tabela e nesse momento ele j\u00e1 deixa um espa\u00e7o reservado para essa nova coluna. Agora, sua coluna com valores NULL passa a ocupar espa\u00e7o em disco novamente.<\/p>\n<p>Visualizando:<\/p>\n<p>ALTER INDEX PK_Teste_NULL on Teste_NULL REBUILD<\/p>\n<p><a href=\"https:\/\/www.fabriciolima.net\/blog\/wp-content\/uploads\/2012\/02\/spaceusedTabelas3.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-1326\" title=\"spaceusedTabelas3\" src=\"https:\/\/www.fabriciolima.net\/blog\/wp-content\/uploads\/2012\/02\/spaceusedTabelas3.png\" alt=\"\" width=\"386\" height=\"108\" srcset=\"https:\/\/fabriciolima.net\/blog\/wp-content\/uploads\/2012\/02\/spaceusedTabelas3.png 386w, https:\/\/fabriciolima.net\/blog\/wp-content\/uploads\/2012\/02\/spaceusedTabelas3-300x84.png 300w, https:\/\/fabriciolima.net\/blog\/wp-content\/uploads\/2012\/02\/spaceusedTabelas3-100x28.png 100w, https:\/\/fabriciolima.net\/blog\/wp-content\/uploads\/2012\/02\/spaceusedTabelas3-275x77.png 275w, https:\/\/fabriciolima.net\/blog\/wp-content\/uploads\/2012\/02\/spaceusedTabelas3-20x6.png 20w\" sizes=\"auto, (max-width: 386px) 100vw, 386px\" \/><\/a><\/p>\n<p>Como podem perceber, agora a nova coluna do tipo datetime e com valores somente NULL passou a ocupar espa\u00e7o em disco.<\/p>\n<p>Espero que tenha ajudado a esclarecer esse mito que \u00e9 comum de ouvirmos no nosso dia a dia.<\/p>\n<p><b>Gostou desse Post?<\/b><\/p>\n<p>Cadastre seu e-mail para receber novos Posts e curta minha <a href=\"https:\/\/www.facebook.com\/FabricioLimaSolucoesemBancodeDados\/\" target=\"_blank\">P\u00e1gina no Facebook<\/a> para receber Dicas de Leituras e Eventos sobre SQL Server.<\/p>\n<p>Abra\u00e7os,<\/p>\n<p>Fabr\u00edcio Lima<\/p>\n<p>MCITP \u2013 Database Administrator<\/p>\n<p>Consultor e Instrutor SQL Server<\/p>\n<p>Trabalha com SQL Server desde 2006<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Ol\u00e1 Pessoal, Muitos de voc\u00eas j\u00e1 devem ter recebido a seguinte solicita\u00e7\u00e3o: &#8220;Favor criar uma coluna nova na tabela X (80 milh\u00f5es de linhas). Como os valores existentes ser\u00e3o NULLs, esse campo n\u00e3o ocupar\u00e1 espa\u00e7o em disco e n\u00e3o teremos nenhum impacto nessa tabela&#8220;. Entretanto, n\u00e3o \u00e9 exatamente isso que acontece! Tipos de dados que [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_exactmetrics_skip_tracking":false,"_exactmetrics_sitenote_active":false,"_exactmetrics_sitenote_note":"","_exactmetrics_sitenote_category":0,"footnotes":""},"categories":[3,6,280],"tags":[90,594,595,596,93,23,91,598,600,602,601,599,33,597],"class_list":["post-1323","post","type-post","status-publish","format-standard","hentry","category-administracao-de-bd","category-casos-do-dia-a-dia","category-virtual-pass-br","tag-alter-table","tag-campos-null","tag-campos-null-ocupam-espaco","tag-colunas-null-ocupam-espaco","tag-create-table","tag-dba","tag-espaco-em-disco","tag-espaco-em-disco-com-null","tag-mito","tag-mito-sql","tag-mitos-sql-server","tag-null","tag-sql-server","tag-valores-null-ocupam-espaco"],"post_mailing_queue_ids":[],"_links":{"self":[{"href":"https:\/\/fabriciolima.net\/blog\/wp-json\/wp\/v2\/posts\/1323","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/fabriciolima.net\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/fabriciolima.net\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/fabriciolima.net\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/fabriciolima.net\/blog\/wp-json\/wp\/v2\/comments?post=1323"}],"version-history":[{"count":0,"href":"https:\/\/fabriciolima.net\/blog\/wp-json\/wp\/v2\/posts\/1323\/revisions"}],"wp:attachment":[{"href":"https:\/\/fabriciolima.net\/blog\/wp-json\/wp\/v2\/media?parent=1323"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/fabriciolima.net\/blog\/wp-json\/wp\/v2\/categories?post=1323"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/fabriciolima.net\/blog\/wp-json\/wp\/v2\/tags?post=1323"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}