Freitag, 1. März 2019

SQL-Server entrümpeln



Unser Testsystem ist vollgelaufen, weil jeder da was ablegt, sich aber dann nicht mehr darum kümmert, ob das auch weg kann.

Nun gibt es zwei Szenarien, nachdem man suchen könnte:

Szenario 1: Löschen, was weg muss

Alles was nach einem Ablaufdatum noch da ist, muss weg. Das heißt, ich brauche  das Datum, wann die Datenbank erstellt wurde (hier: crDate) und wann der letzte Zugriff darauf erfolgte (hier chDate).


select d.Name, dbID, crDate, chDate =
(select lastdate = max(bb.xx) 
from (
    select xx = max(last_user_seek) 
        where max(last_user_seek) is not null 
    union all 
    select xx = max(last_user_scan) 
        where max(last_user_scan) is not null 
    union all 
    select xx = max(last_user_lookup) 
        where max(last_user_lookup) is not null 
    union all 
        select xx = max(last_user_update) 
        where max(last_user_update) is not null) bb)
, filename as Pfad
FROM master.dbo.sysdatabases d 
left outer join 
sys.dm_db_index_usage_stats s 
on d.dbid= s.database_id 
group by d.name, dbid, crdate, filename

Aber Achtung; das Datum wird bei Neustart des Rechners auf NULL gesetzt.



Szenario 2: Löschen, was sich lohnt

Wenn es sowieso ein Test-System ist, kann ja theoretisch alles weg. Man könnte aber auch vor allem denen auf die Füße treten, deren Datenbanken den meisten Platz beanspruchen. Hier muss man über eine Zwischentabelle arbeiten, weil die Size-Werte nicht nach MASTER übergeben werden:


use master;

set TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
GO

declare @Result Table (
 Database_Name sysname NOT NULL,
 Database_Owner sysname NULL,
 type_desc VARCHAR(10) NOT NULL,
 size_MB DECIMAL(18, 2) NOT NULL DEFAULT (0),
 used_MB DECIMAL(18, 2) NOT NULL DEFAULT (0),
 growth_MB DECIMAL(18, 2) NOT NULL DEFAULT (0),
 is_percent_growth TINYINT NOT NULL DEFAULT (0),
    PRIMARY KEY CLUSTERED (
        Database_Name,
        logical_name      ),
    UNIQUE (physical_name),
 Logical_Name sysname NOT NULL,
 physical_name VARCHAR(255) NOT NULL,
 compatibility_level VARCHAR(10) NOT NULL,
 collation_Name sysname NOT NULL,
 snapshot_isolation VARCHAR(5) NOT NULL DEFAULT ('OFF'),
 read_committed_SI TINYINT NOT NULL DEFAULT (0)
);
 
INSERT INTO @Result
EXEC    sys.sp_MSforeachdb @command1 = N'USE [?];
select
  DB_NAME(D.database_id) as [Database Name],
        SP.name as [Database_Owner],
        MF.type_desc,
        MF.size / 128.0  AS [size_MB],
        FILEPROPERTY(MF.name, ''spaceused'') / 128.0      AS [used_MB],
        CASE WHEN MF.[is_percent_growth] = 1
            THEN MF.[size] * (MF.[growth] / 100.0)
            ELSE MF.[growth]
        END    / 128.0  AS [growth_MB],
        MF.[is_percent_growth],
        MF.name,
        MF.physical_name,
        D.compatibility_level,
        D.collation_name,
        D.snapshot_isolation_state_desc,
        D.is_read_committed_snapshot_on
from    sys.databases AS D INNER JOIN sys.master_files AS MF
        ON    (D.database_id = MF.database_id) LEFT JOIN sys.server_principals AS SP
        ON    (D.owner_sid = SP.sid)
where    D.database_id = DB_ID();';
 
select * from @Result AS R order by type_desc desc, size_MB desc;
 

SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
GO

Hier müssen die LOGs und die Datenbanken separat betrachtet werden.



Keine Kommentare:

Kommentar veröffentlichen

Farbe ist das neue Schwarz

Das gute alte Batch - sie funktioniert und tut, aber leider ist sie so schwarz und unschön. Dabei gibt es von (nahezu) Anfang an die Möglich...