Så populære som cloud-tjenesterne er i dag, er der stadig en god del af lokale implementeringer af SQL Server, som stadig kræver, at vores tjenester understøtter dem. Et af de områder af lokale opsætninger, som vi skal holde øje med, er opbevaring, lige der hvor dataene gemmes.
Jeg vil præsentere dig for en lagret procedure til at visualisere vigtige lagerpladsoplysninger i din SQL Server-instans.
Indledende overvejelser
- Sørg for, at kontoen, der udfører denne lagrede procedure, har nok privilegier.
- Databaseobjekterne (databasetabel og lagret procedure) vil blive oprettet i den database, der er valgt på det tidspunkt, hvor scriptet udføres, så vælg med omhu.
- Scriptet er lavet på en måde, så det kan udføres flere gange uden at få en fejlmeddelelse til dig. Til den lagrede procedure brugte jeg CREATE OR ALTER PROCEDURE-sætningen, tilgængelig siden SQL Server 2016 SP1.
- Du er velkommen til at ændre navnet på de oprettede databaseobjekter.
- Når du vælger at bevare data, der returneres af den lagrede procedure, afkortes måltabellen først, så kun det seneste resultatsæt gemmes.
- Husk på, at denne løsning ikke giver mening i cloud-implementeringer, hvor cloud-udbyderen administrerer tingene for dig, og du ikke har adgang til filsystemet.
Hvordan bruges lagret procedure?
- Kopiér og indsæt TSQL-koden (tilgængelig i denne artikel).
- SP forventer 2 parametre:
- @persistData:'Y', hvis DBA'en ønsker at gemme outputtet i en måltabel, og 'N', hvis DBA'en kun ønsker at se outputtet direkte.
- @driveDetail:Selvom det er valgfrit, hvis du sender et drevbogstav, har @persistData-parameteren ingen som helst effekt.
Felter præsenteret og deres betydning
- drev: drevbogstavet, der indeholder datafiler for den aktuelle instans.
- total_space: størrelsen af drevet i GBs.
- friplads: mængden af tilbageværende GB i drevet.
- used_space: mængden af GB, der er optaget af alle databaser i instansen.
- data_indsamling_tidsstempel: kun synlig, hvis 'Y' sendes til @persistData-parameteren, og den bruges til at vide, hvornår SP'en blev udført, og informationen blev gemt i DBA_Storage-tabellen.
Udførelsestest
Jeg vil demonstrere et par udførelser af den lagrede procedure, så du kan få en idé om, hvad du kan forvente af den:
EXEC GetStorageData @persistData = 'N'
Da jeg kørte dette i en testforekomst, hvor jeg har alt proppet i C:\-drev (jeg ved, den værste praksis nogensinde), blev der kun returneret én række. Lad mig nu vise dig et skærmbillede af brugen af mit C:\-drev, som rapporteret af Windows, bare for at se, om SP'en ikke bluffer rundt:
Det ser godt ud, for det meste. Men hvis du kigger nærmere, vil du bemærke, at "Used space" i grafikken siger 25GB og SP siger "0.170GB", det er mærkeligt ikke? Nå, grunden er, at betydningen i SP er en smule anderledes:her rapporterer den mængden af GB, der kun er optaget af databasefiler, så husk det.
Nu virker det output lidt tørt, ikke? Jeg mener, vi ved ikke, hvad der præcist tager den rapporterede brugte plads. Det er her den anden parameter spiller ind, så lad os tjekke det ud:
EXEC GetStorageData @persistData = 'N', @driveDetail = 'C'
Hvis du udfører det på denne måde, får du listen over specifikke databaser, der har mindst 1 databasefil i drevet, der er sendt som parameter. Hvis du summerer kolonnen "samlet rum", vil det give dig nøjagtig samme værdi som det tidligere opsummerede output.
Lad mig prøve en ting mere for at se, hvad SP'en returnerer. Jeg vil oprette en ny database, men jeg vil placere databasefilerne i et andet drev, som jeg har liggende. Jeg kalder databasen "test", og jeg placerer den i drev S:\.
Så nu udsender SP også det drev i resultatsættet. Men igen, lad os se, hvad der sker, hvis vi smider parameteren @driveDetail med 'S' som værdi:
Bingo, det rapporterer den "test"-database, jeg oprettede med den størrelse, jeg valgte (1 GB til datafilen og 8 MB for transaktionslogfilen).
Sideforespørgsler
Nu, for at levere mere værdi til DBA, har jeg forberedt et par forespørgsler, der kan hjælpe dig med at få nyttige oplysninger fra de data, der findes i tabellen.
*Forespørgsel for at finde databaser med mindst 1 datafil hostet i C:\-drevet.
SELECT * FROM DBA_Storage WHERE drive = 'C:\';
*Forespørgsel for at visualisere listen over drev sorteret efter free_space, fra laveste til højeste. Med dette kan du vide, hvilke drev der kræver din opmærksomhed så hurtigt som muligt.
SELECT * FROM DBA_Storage ORDER BY free_space;
*Forespørgsel for at visualisere listen over drev sorteret efter used_space, fra højeste til laveste. Med dette kan du vide, hvilke der har flere data end de andre.
SELECT * FROM DBA_Storage ORDER BY used_space DESC;
Her er den komplette kode for den lagrede procedure:
*I begyndelsen af scriptet vil du se standardværdien, som den lagrede procedure antager, hvis der ikke sendes nogen værdi for hver parameter.
CREATE OR ALTER PROCEDURE [dbo].[GetStorageData]
@persistData CHAR(1) = 'Y',
@driveDetail CHAR(1) = NULL
AS
BEGIN
SET NOCOUNT ON
DECLARE @command NVARCHAR(MAX)
DECLARE @Tmp_StorageInformation TABLE(
[drive] [CHAR](3) NOT NULL,
[total_space] [DECIMAL](10,3) NOT NULL,
[free_space] [DECIMAL](10,3) NOT NULL,
[used_space] [DECIMAL](10,3) NOT NULL
)
IF NOT EXISTS (SELECT * FROM dbo.sysobjects where id = object_id(N'DBA_Storage') and OBJECTPROPERTY(id, N'IsTable') = 1)
BEGIN
CREATE TABLE DBA_Storage(
[drive] [CHAR](3) NOT NULL,
[total_space] [DECIMAL](10,3) NOT NULL,
[free_space] [DECIMAL](10,3) NOT NULL,
[used_space] [DECIMAL](10,3) NOT NULL,
[data_collection_timestamp] [DATETIME] NOT NULL
)
END
IF(@driveDetail IS NOT NULL)
BEGIN
SELECT DB_NAME(mf.database_id) AS 'database',CONVERT(DECIMAL(10,3),SUM(size*8)/1024.0/1024.0) AS 'total space'
FROM sys.master_files mf
WHERE SUBSTRING(mf.physical_name,0,4) = CONCAT(@driveDetail,':\')
GROUP BY mf.database_id
RETURN
END
INSERT INTO @Tmp_StorageInformation
SELECT
drives.drive,
drives.total_space,
drives.free_space,
(SELECT CONVERT(DECIMAL(10,3),SUM(size*8)/1024.0/1024) FROM sys.master_files WHERE SUBSTRING(physical_name,0,4) = drives.drive) AS 'used_space'
FROM(
SELECT DISTINCT vs.volume_mount_point AS 'drive',CONVERT(DECIMAL(10,3),(vs.available_bytes/1048576)/1024.0) AS 'free_space',CONVERT(DECIMAL(10,3),(vs.total_bytes/1048576)/1024.0) AS 'total_space'
FROM sys.master_files mf
CROSS APPLY sys.dm_os_volume_stats(mf.database_id,mf.file_id) vs
) AS drives
IF @persistData = 'N'
SELECT * FROM @Tmp_StorageInformation
ELSE
BEGIN
TRUNCATE TABLE DBA_Storage
INSERT INTO DBA_Storage
SELECT *,GETDATE() FROM @Tmp_StorageInformation ORDER BY [drive]
END
END
Konklusion
- Du kan implementere denne SP i alle SQL Server-instanser under din support og implementere en advarselsmekanisme på tværs af hele din stak af understøttede instanser.
- Hvis du implementerer et agentjob, der forespørger om disse oplysninger relativt ofte, kan du være på forkant med spillet med hensyn til at tage trinene til at tage sig af opbevaringen, når bestemte tærskler er nået, inden for dine(de) understøttede miljø(er) .
- Sørg for at tjekke flere værktøjer, der er udgivet her på CodingSight.