Existe uma maneira confiável de determinar quando você deve executar o DBCC CLEANTABLE para recuperar espaço?

11

Ultimamente, em vez de apenas aumentar arquivos quando eles alcançam 80% de utilização, tenho sido mais proativo na recuperação de espaço por meio de truques comuns como desfragmentar pilhas, adicionar e soltar índices agrupados, implementar compactação de linhas ou páginas etc.

No entanto, existem alguns casos em que consegui recuperar ainda mais espaço executando o DBCC CLEANTABLE . Com centenas de bancos de dados em meu ambiente, não é possível saber o que os usuários fazem em cada um deles e é completamente aceitável que ocorram alterações envolvendo a eliminação de colunas de comprimento fixo. Normalmente, encontrei essas oportunidades examinando as contagens de linhas x contagens de páginas em alguns scripts de utilização de espaço de objeto que escrevi. Eu gostaria de dar um passo adiante, tentando automatizar a detecção desse tipo de cenário.

O que eu gostaria de saber é se alguém por aí está monitorando ativamente esse tipo de oportunidade e, se sim, o que você procura especificamente?

Meu pensamento era escrever algo como reunir o tamanho máximo e mínimo de uma linha, o número de linhas na tabela, o número de páginas alocadas e o número de páginas usadas, depois fazer algumas contas básicas para registrar resultados que estão bem fora do que seria "esperado".

AndrewSQL
fonte
Eu recomendo usar o parâmetro batch_size em tabelas grandes. Isso fará com que o comando seja executado em uma série de transações, em oposição a uma transação gigante.
datagod

Respostas:

11

A solução que eu pensaria para esse problema é executar semanalmente um trabalho que executará sp_spaceused para todas as tabelas em um banco de dados e salve esses dados em uma tabela. Se houver diferenças no tamanho de cada tabela maior que ... digamos ... 10%, eu executaria a tabela limpa dbcc.

Meu código para percorrer os tamanhos das tabelas é assim:

if OBJECT_ID ('tempdb.dbo.#temp') is not null
    drop table #temp;

if OBJECT_ID ('dbo.BigTables') is not null
    drop table dbo.BigTables;
go

CREATE TABLE [dbo].[BigTables] (
    [table_name] [sysname] NOT NULL,
    [row_count] [int] NULL,
    [col_count] [int] NULL,
    [data_size] [varchar](50) NULL,
    [Date] [datetime] NOT NULL,
    [DBName] [nvarchar](128) NULL
);
GO

CREATE TABLE #temp (
    table_name sysname ,
    row_count int,
    reserved_size varchar(50),
    data_size varchar(50),
    index_size varchar(50),
    unused_size varchar(50)
);
go

INSERT     #temp
EXEC       sp_msforeachtable 'sp_spaceused ''?'''

insert into dbo.BigTables
SELECT     a.table_name,
           a.row_count,
           count(*) as col_count,
           a.data_size,
           getdate() as [Date],
    'MY DB' as DBName
FROM       #temp a
INNER JOIN information_schema.columns b
           ON a.table_name collate database_default
                = b.table_name collate database_default
GROUP BY   a.table_name, a.row_count, a.data_size
ORDER BY   CAST(Replace(a.data_size, ' KB', '') as integer) desc

DROP TABLE #temp;

Select * from dbo.BigTables;

Agora você só precisa criar a lógica que verificará qual seria a alteração de tamanho durante a semana e a agendará.

Marian
fonte
Agora, se houver motivos para suspeitar de imprecisões nos relatórios de tamanho da tabela, você deve procurar DBCC UPDATEUSAGE (isso corrigirá as contagens de linhas e páginas). Feliz por ajudar!
Marian