Olá, bom dia. Tudo bem?
O frio já chegou na sua região? Aqui em São Roque, interior de São Paulo, hoje esta manhã esta sendo considerada até o presente momento a mais fria do ano (eu particularmente adoro o frio).
Fico extremamente contente e honrado com a sua visita ao meu blog, mesmo com todo este frio ter a sua presença aqui é muito importante, ainda mais neste post da sessão Dica do Mês, a qual foi criada á alguns anos com objetivo de compartilhar algo que possa ser considerada como uma dica ou melhores práticas para se trabalhar na área de banco de dados, mais especificamente falando relacionadas ao Microsoft SQL Server.
Posso dizer que o post de hoje é algo bastante simples, vamos conhecer um pouco mais sobre um dos mais tradicioais comandos pertencentes a categoria DBCC – Database Command Console existente no Microsoft SQL Server desde suas versões iniciais.
Estou me referindo ao comando DBCC CleanTable, considerado por muitos DBAs o “Veja, aquele produto de limpeza que utilizamos para tirar a gordura dos fogões e panelas”, ele faz basicamente isso em nossas tabelas. No decorrer deste post vou tentar mostrar como Podemos fazer isso.
Sendo assim, sem mais delongas, vamos em frente, vou tentar mitigar a sua curiosidade e ao mesmo também satisfazer os meus objetivos. Seja bem-vindo ao post – Dica do Mês – Analisando o comportamento do comando DBCC Clean Table.
Introdução
O Microsoft SQL Server apresenta em sua galeria de comandos um conjunto muito particular e exclusivo denominado DBCC – Database Command Console em uma possível tradução para o Português “Comandos de Console de Banco de Dados“, pois bem, este conjunto com categoria de comandos é composta por uma relação bem interessante e diversificada que nos permite fazer uso em diversos cenários, dentre eles por exemplos os comandos: DBCC CheckDB ou DBCC ShrinkFile, ambos muito conhecidos pelos DBAs e Administradores de Banco de Dados, caso você ainda não conheça, com certeza em algum momento terá a oportunidade.
Como já destaquei nesta relação exclusiva de comandos, podemos se deparar com um deles que nos permite aplicar sem qualquer tipo de alteração de configuração, ou mudanças drásticas na estrutura de nosso banco de dados, o que chamamos de remover a gordura de nossas tabelas, talvez você não consiga ou não esteja entendendo o que eu estou definindo como “gordura”, na verdade me refiro por exemplo a aquelas colunas do tipo de dados VarChar, criadas inicialmente em nossas tabelas, mas que ao longo do tempo se tornam colunas praticamente consideradoras espúrias (algo sem sentido ou desnecessário), é ai que entra o nosso amigo DBCC CleanTable, ele tem um papel único e específico justamente para este tipo de cenário, que daqui a pouco eu vou demonstrar, mas antes vamos conhecer um pouquinho sobre este comando.
DBCC CleanTable
Adicionado ao Microsoft SQL Server a partir da edição 2008, o comando DBCC CleanTable possui como papel principal a capacidade de recuperar e liberar o espaço ocupado por colunas existentes em uma tabela consideradas colunas com comprimento variável quando utilizam os seguintes tipos de dados:
- Varchar;
- Nvarchar;
- Varchar(max);
- Nvarchar(max);
- Varbinary;
- Varbinary(max);
- Text;
- Ntext;
- Image;
- Sql_variant; e
- XML.
Ele recupera espaço anteriormente ocupado por um destes tipos de dados, depois que uma coluna de comprimento variável é descartada, mas não recupera espaço depois que uma coluna de comprimento fixo é descartada.
Mesmo não tem a capacidade de recuperar o espaço ocupado em disco logo após este limpeza na estrutura da tabela, o comando DBCC CleanTable, pode ajudar a melhorar ou até mesmo zerar taxas de fragmentação que possam estar sendo apresentadas justamente em uma tabela devido a utilização destas colunas com comprimentos variáveis.
Considerações
- As colunas descartadas forem armazenadas em linha, DBCC CLEANTABLE recuperará espaço da unidade de alocação IN_ROW_DATA da tabela.
- Quando as colunas forem armazenadas fora de linha, o espaço será recuperado da unidade de alocação LOB_DATA ou ROW_OVERFLOW_DATA, dependendo do tipo de dados da coluna descartada.Se o espaço recuperado de uma página ROW_OVERFLOW_DATA ou LOB_DATA resultar em uma página vazia, DBCC CLEANTABLE removerá a página. DBCC CLEANTABLE executa como uma ou mais transações.
- O espaço recuperado de uma página ROW_OVERFLOW_DATA ou LOB_DATA resultar em uma página vazia, DBCC CLEANTABLE removerá a página. DBCC CLEANTABLE executa como uma -ou mais transações.
- Caso não especificado um tamanho de lote, o comando processará a tabela inteira em uma transação e a tabela será bloqueada exclusivamente durante a operação. Para algumas tabelas grandes, o comprimento da única transação e o espaço do log requeridos podem ser muito grandes. Se um tamanho de lote for especificado, o comando executará em uma série de transações, cada qual incluindo o número especificado de linhas.
- O comando DBCC CLEANTABLE não pode ser executado como uma transação dentro de outra transação. Essa operação é totalmente registrada. Não há suporte para DBCC CLEANTABLE para uso em tabelas do sistema, tabelas temporárias ou a parte do índice columnstore xVelocity de memória otimizada de uma tabela.
Evite utilizar
O comando DBCC CLEANTABLE não deve ser executado como uma tarefa de manutenção de rotina. Ao invés disso, utilize o DBCC CLEANTABLE depois de fazer mudanças significativas em colunas de comprimento variável em uma tabela ou exibição indexada e necessita recuperar o espaço sem-uso (considerada como área não alocada) prontamente.
Alternativas para o uso do DBCC CleanTable
Uma das possíveis alternativas quando desejamos recuperar o espaço ocupado por colunas de comprimemto variável aplica-se a reconstrução de índices em tabelas ou visões indexadas, mas este recurso pode ser considerado custoso no que se relaciona ao tempo de processamento ou até mesmo alocação de recursos durante sua execução.
Pois bem, agora que já conhecemos um pouco sobre este comando, suas considerações, o quando usar e não usar, vamos avançar um pouco este post, dando início a nosso cenário de estudos afim de analisarmos de uma forma bem simples e artificial como o DBCC CleanTable pode nos ser útil.
NOSSO AMBIENTE
Como de costume vamos utilizar um ambiente isolado dos demais bancos de dados que você possa conter, desta maneira nosso cenário será constituído dos seguintes elementos:
- Banco de Dados: TesteDBCCCleanTable;
- Arquivo Texto: QueimadasCleanTable (100 MBs – Dados – Queimadas 2002); e
- Tabela: QueimadasCleanTable.
Observações
- Estaremos fazendo uso de um arquivo texto, o qual é parte importante para nossa análise. O mesmo possui os dados que serão importados para o Microsoft SQL Server, contendo com conjunto real de valores coletados através do portal do INPE – Instituto Nacional de Pesquisas Especiais, através de seu Banco de Dados de análise de queimadas ocorridas no Brasil ao longo dos últimos 70 anos, sendo considerada uma das mais importantes fontes de dados abertos do Brasil, disponível para qualquer tipo de análise. Particularmente falando, sou um grande admirador do trabalho realizado pelo INPE, o qual eu comecei em 2017 a estudar para um dos meus projetos no mestrado e diretamente relacionados com a minha nova área de estudos: Data Warehouse, Data Mining e BI.
- A estrutura apresentada no arquivo texto, não tem por finalidade ou regra ser considerada uma estrutura padronizada, como também, algo que atenda as regras da Normalização, longe disso, todo conjunto de dados, tipos de dados, nomes das colunas e sua composição física e lógica foi definida e criada para atender as regras de negócio muito específicas de um trabalho de mestrado acadêmico, o qual não faz parte deste estudo ou análise.
- O objetivo deste post não se realiza a apresentar, demonstrar ou orientar como realizar o procedimento de importação de dados para o Microsoft SQL Server, sendo assim, caso você tenha dúvidas ou dificuldades para realizar este procedimento, acesse: Import and Export Data with the SQL Server Import and Export Wizard.
- Logo após a execução do processo de importação dos dados, você notará que nossa tabela e sua estrutura foi criada sem respeitar uma análise de uso de tipos de dados, criação de chaves primárias ou outras considerações que podemos definir como melhores práticas de modelagem de banco de dados. Não foi fique preocupado, pois estaremos realizando toda esta reestruturação logo na sequência.
Avançando mais um pouco, vamos criar nosso banco de dados e logo na sequência começaremos nossa análise, para tais procedimentos, utilizaremos o Bloco de Código 1 abaixo:
— Bloco de Código 1 – Criando nosso cenário —
— Criando o Banco de Dados —
Create Database TesteDBCCCleanTable
Go
— Acessando o Banco de Dados —
Use TesteDBCCCleanTable
Go
Presumo que neste momento você já tenha feito download do arquivo QueimadasTableCleanTable.txt, como também, já tenha realizado a importação dos dados e criação da tabela,.
Ótimo, espero que todo processo de importação de dados tenha ocorrido corretamente, agora com a estrutura criada e acessível, teremos a possibilidade de começar a realizar nossa análise, nosso próximo passo será reestrutura a tabela QueimadasCleanTable, definindo sua chave primária, alterando tipos de dados em determinadas colunas, removendo outras, enfim colocando um pouco de ordem na casa.
Desta forma, vamos utilizar o Bloco de Código 2 a seguir:
— Bloco de Código 2 – Reestruturando a Tabela QueimadasCleanTable —
Alter Table QueimadasCleanTable
Alter Column CodigoQueimada Int Not Null
Go
Alter Table QueimadasCleanTable
Add Constraint [PK_QueimadasCleanTable_Codigo]
Primary Key (CodigoQueimada)
Go
Alter Table QueimadasCleanTable
Alter Column Pais Char(6) Not Null
Go
Alter Table QueimadasCleanTable
Alter Column Satelite Varchar(10) Not Null
Go
Alter Table QueimadasCleanTable
Alter Column Municipio Varchar(40) Not Null
Go
Alter Column Estado Varchar(20) Not Null
Go
Alter Column Bioma Varchar(15) Not Null
Go
Update QueimadasCleanTable
Set DataHora=Convert(DateTime, DataHora, 102)
Go
Alter Table QueimadasCleanTable
Alter Column DataHora DateTime Not Null
Go
Alter Table QueimadasCleanTable
Alter Column Longitude Numeric(10,5) Not Null
Go
Alter Table QueimadasCleanTable
Alter Column Latitude Numeric(10,5) Not Null
Go
Ufa, após este longo caminho percorrido, nossa tabela QueimadasCleanTable, deve estar apresentando uma estrutura similar a Figura 1:
Figura 1 – Banco de Dados TesteDBCCCleanTable e Tabela QueimadasCleanTable criados.
Sensacional, agora a brincadeira vai começar, devemos ter basicamente 752.252 (Setecentas e cinquenta e duas mil, duzentas e cinquenta e duas) linhas de registros lógicos inseridas nesta tabela, uma massa de dados interessante e bem diversificada para nosso estudo, afim de confirmarmos nossas massa de dados, vamos executar o Bloco de Código 3 a seguir, para retornarmos em tela uma pequena porção de dados:
— Bloco de Código 3 – Validando uma porção de dados da Tabela QueimadasCleanTable —
Select Top 1000 DataHora,
Satelite,
Pais,
Estado,
Municipio
From QueimadasCleanTable
Go
Após a execução do Bloco de Código 3, você deverá ter obtido em tela, um resultado similar ao apresentado abaixo pelo Figura 2:
Figura 2 – Dados coletados e apresentados em tela após a execução do Bloco de código 3.
Por enquanto nenhuma novidade, nada em especial foi apresentado, não é mesmo? Eu acredito que sim. Agora que toda estrutura da tabela foi refeita, nossos dados foram validados, o que pode estar faltando para fazermos uso do comando DBCC CleanTable?
A resposta é simples, falta identificar quais são as colunas de comprimento variável existentes em nossa tabela que poderemos utilizar para entender o comportamento deste comando, sendo assim, nosso próximo passo será identificar quais seriam as colunas e seus respectivos tipos de dados que formam a estrutura da tabela QueimadasCleanTable, através da execução do Bloco de Código 4 apresentado abaixo:
— Bloco de Código 4 – Identificando as colunas de comprimento variável —
Select st.name As ‘TableName’,
sc.name As ‘ColumnName’,
sc.column_id As ‘ColumnID’,
sty.name As ‘DataType’,
sc.max_length As ‘MaxLength’
from sys.tables st Inner Join sys.columns sc
on st.object_id = sc.object_id
Inner Join sys.systypes sty
on sc.system_type_id = sty.xtype
Where st.name = ‘QueimadasCleanTable’
And sty.name = ‘VarChar’
Order By st.Name Asc, sc.column_id Asc
Go
Note que estamos fazendo uso das conhecidas e tradicionais tabelas de sistema:
- sys.tables;
- sys.columns; e
- sys.systypes.
A execução do Bloco de Código 4 é simples e rápida, a Figura 3 abaixo, deve ilustrar o resultado obtido após sua execução:
Figura 3 – Relação de colunas que utilizam o tipo de dados Varchar() com tamanho variáveis.
Estamos quase lá, já sabemos da existência de 7(sete) colunas que neste momento fazem parte da estrutura da nossa tabela QueimadasCleanTable que nos possibilitam serem utilizadas.
Como eu destaquei anteriormente o comando DBCC CleanTable tem como papel principal recuperar o espaço ocupado por estas colunas, quando as mesmas venham a ser removidas ou sofram alterações em seus tamanhos.
Para que possamos entender de forma clara e didática como o DBCC CleanTable trabalha, temos a necessidade de identificar os espaços ocupados neste momento por nossa tabela, e obrigatoriamente as taxas de alocação e fragmentação de dados, vamos então executar o Bloco de Código 5, o qual vai nos ajudar a identificar o espaçamento ocupado por nossa tabela:
— Bloco de Código 5 – Identificando o espaço e áreas de alocação ocupadas pela Tabela QueimadasCleanTable —
Go
si.name As ‘Índice’,
convert(decimal(5,2),isnull(ddips.avg_fragmentation_in_percent,0)) As ‘% Média de Fragmentação’,
convert(decimal(5,2),isnull(ddips.avg_page_space_used_in_percent,0)) As ‘% Média de Espaço utilizado’,
ddips.page_count As ‘Páginas’,
ddips.compressed_page_count As ‘Páginas compactadas’,
ddips.record_count As ‘Registros’,
ddips.ghost_record_count As ‘Registros Fantasmas’
From sys.dm_db_index_physical_stats(db_id(), object_id(‘QueimadasCleanTable’),null, null, ‘detailed’) ddips Inner Join sys.indexes si
on si.object_id = ddips.object_id
Go
Tabela 1 – SP_SpaceUsed – Espaços Ocupados | |||||
name | rows | reserved | data | index_size | unused |
QueimadasCleanTable | 752252 | 81736 KB | 81272 KB | 312 KB | 152 KB |
Tabela 2 – Sys.dm_db_index_physical_stats – Taxas de Fragmentação, Distribuição de Páginas de Dados e Registros | |||||||
Tabela | Índice | % Média de Fragmentação | % Média de Espaço utilizado | Páginas | Páginas compactadas | Registros | Registros Fantasmas |
QueimadasCleanTable | PK_CodigoQueimada_Queimadas2018_CleanTable | 0.01 | 99.34 | 10159 | 0 | 752252 | 0 |
QueimadasCleanTable | PK_CodigoQueimada_Queimadas2018_CleanTable | 0.00 | 44.07 | 37 | 0 | 10159 | 0 |
QueimadasCleanTable | PK_CodigoQueimada_Queimadas2018_CleanTable | 0.00 | 5.92 | 1 | 0 | 37 | 0 |
Drop Column Municipio, Bioma, AreaIndu, FRP
Go
Go
si.name As ‘Índice’,
convert(decimal(5,2),isnull(ddips.avg_fragmentation_in_percent,0)) As ‘% Média de Fragmentação’,
convert(decimal(5,2),isnull(ddips.avg_page_space_used_in_percent,0)) As ‘% Média de Espaço utilizado’,
ddips.page_count As ‘Páginas’,
ddips.compressed_page_count As ‘Páginas compactadas’,
ddips.record_count As ‘Registros’,
ddips.ghost_record_count As ‘Registros Fantasmas’
From sys.dm_db_index_physical_stats(db_id(), object_id(‘QueimadasCleanTable’),null, null, ‘detailed’) ddips Inner Join sys.indexes si
on si.object_id = ddips.object_id
Go
Go
Go
si.name As ‘Índice’,
convert(decimal(5,2),isnull(ddips.avg_fragmentation_in_percent,0)) As ‘% Média de Fragmentação’,
convert(decimal(5,2),isnull(ddips.avg_page_space_used_in_percent,0)) As ‘% Média de Espaço utilizado’,
ddips.page_count As ‘Páginas’,
ddips.compressed_page_count As ‘Páginas compactadas’,
ddips.record_count As ‘Registros’,
ddips.ghost_record_count As ‘Registros Fantasmas’
From sys.dm_db_index_physical_stats(db_id(), object_id(‘QueimadasCleanTable’),null, null, ‘detailed’) ddips Inner Join sys.indexes si
on si.object_id = ddips.object_id
Go
Tabela 3 – SP_SpaceUsed – Espaços Ocupados | |||||
name | rows | reserved | data | index_size | unused |
QueimadasCleanTable | 752252 | 81736 KB | 81272 KB | 312 KB | 152 KB |
Tabela 4 – Sys.dm_db_index_physical_stats – Taxas de Fragmentação, Distribuição de Páginas de Dados e Registros | |||||||
Tabela | Índice | % Média de Fragmentação | % Média de Espaço utilizado | Páginas | Páginas compactadas | Registros | Registros Fantasmas |
QueimadasCleanTable | PK_CodigoQueimada_Queimadas2018_CleanTable | 0.01 | 80.99 | 10159 | 0 | 752252 | 0 |
QueimadasCleanTable | PK_CodigoQueimada_Queimadas2018_CleanTable | 0.00 | 44.07 | 37 | 0 | 10159 | 0 |
QueimadasCleanTable | PK_CodigoQueimada_Queimadas2018_CleanTable | 0.00 | 5.92 | 1 | 0 | 37 | 0 |
REFERÊNCIAS
https://docs.microsoft.com/en-us/sql/t-sql/database-console-commands/dbcc-cleantable-transact-sql
https://docs.microsoft.com/en-us/sql/t-sql/data-types/data-types-transact-sql
POSTS ANTERIORES
- https://pedrogalvaojunior.wordpress.com/2019/03/27/dica-do-mes-aplicando-analise-combinatoria-no-microsoft-sql-server/
- https://pedrogalvaojunior.wordpress.com/2019/01/22/dica-do-mes-temporal-table-e-o-calor-uma-combinacao-muito-quente/
- https://pedrogalvaojunior.wordpress.com/2018/10/23/dica-do-mes-comando-restore-database-page-restaurando-paginas-de-dados-de-uma-tabela-no-microsoft-sql-server/
- https://pedrogalvaojunior.wordpress.com/2018/07/26/dica-do-mes-ocultando-uma-instancia-em-execucao-do-microsoft-sql-server/
- https://pedrogalvaojunior.wordpress.com/2018/04/25/dica-do-mes-sql-operations-studio-view-as-chart/
- https://pedrogalvaojunior.wordpress.com/2018/03/14/dica-do-mes-microsoft-sql-server-2017-sql-graph-databases/
- https://pedrogalvaojunior.wordpress.com/2018/01/24/dicadomes-sqlservertoolsuiteintroduction/
CONCLUSÃO
Como de costume, tenho um imenso prazer em poder compartilhar um pouco das minhas experiências, estudos e conhecimentos que estou diariamente formando sobre este fantástico Sistema Gerenciador de Banco de Dados chamado Microsoft SQL Server.
Neste post, tivemos a possibilidade de relembrar um pouco sobre os comandos DBCCs, mais especificamente o DBCC CleanTable, conhecido como o “Veja, desengordurante, das estruturas de tabelas e visões índexadas” existente no Microsoft SQL Server.
O uso desta comando pode ser aplicado, como uma ferramenta de apoio quando temos a necessidade de reaproveitar o espaço antes ocupado por áreas que pertenciam a uma ou mais colunas que venham a utilizar tipos de dados com tamanhos variáveis.
O comando DBCC CLEANTABLE não deve ser executado como uma tarefa de manutenção de rotina, mas sim, como um recurso aplicado em momento específicos e não de uso contínuo.
Através do cenário aqui apresentado, foi possível observar, como este comando é capaz de resdistribuir e aproveitar o espaço ocupado internamente, sem nos forçar a realizar alterações drásticas em nossas tabelas, bem como, mudanças nas configurações do nosso banco de dados ou SQL Server.
Este é o fantástico Microsoft SQL Server, produto tão fascinante que a cada dia eu não consigo deixar de querer estudar e conhecer mais ainda.
Agradecimentos
Agradeço a você por sua atenção e visita ao meu blog. Fique à vontade para enviar suas críticas, sugestões, observações e comentários.
Nos encontramos no próximo post da sessão Dica do Mês a ser publicado em breve.
Um forte abraço.
Até mais.