Czy istnieje niezawodny sposób na określenie, kiedy należy uruchomić DBCC CLEANTABLE, aby odzyskać miejsce?

11

Ostatnio zamiast tylko powiększania plików, gdy ich wykorzystanie jest zbliżone do 80%, byłem bardziej proaktywny w odzyskiwaniu miejsca za pomocą zwykłych sztuczek, takich jak defragmentacja hałd, dodawanie i usuwanie indeksów klastrowych, wdrażanie kompresji wierszy lub stron itp.

Jednak istnieje kilka przypadków, w których mogłem odzyskać jeszcze więcej miejsca, wykonując DBCC CLEANTABLE . Z setkami baz danych w moim środowisku nie można wiedzieć, co użytkownicy robią w każdym z nich, i jest całkowicie akceptowalne, że nastąpią zmiany polegające na upuszczaniu kolumn o stałej długości. Zazwyczaj znalazłem te możliwości, patrząc na liczbę wierszy w porównaniu z liczbą stron w niektórych skryptach wykorzystujących przestrzeń obiektową, które napisałem. Chciałbym pójść o krok dalej, próbując zautomatyzować wykrywanie tego rodzaju scenariuszy.

Chciałbym wiedzieć, czy ktoś tam aktywnie monitoruje tego rodzaju możliwości, a jeśli tak, to czego konkretnie szukasz?

Myślałem o napisaniu czegoś w taki sposób, aby zebrać maksymalny i minimalny rozmiar wiersza, liczbę wierszy w tabeli, liczbę przydzielonych stron i liczbę używanych stron, a następnie zrobić podstawową matematykę, aby zapisać wyniki, które są daleko poza tym, czego można by się było spodziewać.

AndrewSQL
źródło
Zdecydowanie polecam użycie parametru batch_size na dużych tabelach. Spowoduje to, że polecenie zostanie uruchomione w serii transakcji, a nie w jednej wielkiej transakcji.
data dnia

Odpowiedzi:

11

Rozwiązaniem, które wymyśliłem dla tego problemu, jest uruchamianie co tydzień zadania, które będzie uruchamiać sp_spaceused dla wszystkich tabel w bazie danych i zapisywać te dane w tabeli. Jeśli istnieją różnice w wielkości dla każdej tabeli większe niż ... powiedzmy ... 10%, uruchomiłbym dbcc dający się wyczyścić.

Mój kod do przełączania rozmiarów tabel wygląda następująco:

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;

Teraz wystarczy zbudować logikę, która zweryfikuje, jaka byłaby zmiana rozmiaru w ciągu tygodnia i zaplanować.

Marian
źródło
Teraz, jeśli istnieją powody, by podejrzewać niedokładności w raportach wielkości tabeli, powinieneś wybrać DBCC UPDATEUSAGE (to naprawi liczbę wierszy i stron). Cieszę się, że mogę pomóc!
Marian