Lika populära som molntjänsterna är nuförtiden, finns det fortfarande en stor del av lokala distributioner av SQL Server som fortfarande kräver våra tjänster för att stödja dem. Ett av områdena för lokala inställningar som vi måste hålla ett öga på är lagring, precis där data sparas.
Jag kommer att presentera en lagrad procedur för att visualisera viktig information om lagringsutrymme i din SQL Server-instans.
Inledande överväganden
- Se till att kontot som kör denna lagrade procedur har tillräckligt med privilegier.
- Databasobjekten (databastabell och lagrad procedur) kommer att skapas i den databas som valts vid den tidpunkt då skriptet körs, så välj med omsorg.
- Skriptet är skapat på ett sätt så att det kan köras flera gånger utan att få ett felmeddelande till dig. För den lagrade proceduren använde jag CREATE OR ALTER PROCEDURE-satsen, tillgänglig sedan SQL Server 2016 SP1.
- Ändra gärna namnet på de skapade databasobjekten.
- När du väljer att bevara data som returneras av den lagrade proceduren, kommer måltabellen först att trunkeras så att endast den senaste resultatuppsättningen kommer att lagras.
- Tänk på att den här lösningen inte är vettig i molninstallationer där molnleverantören hanterar saker åt dig och du inte har tillgång till filsystemet.
Hur använder man lagrad procedur?
- Kopiera och klistra in TSQL-koden (tillgänglig i den här artikeln).
- SP:n förväntar sig två parametrar:
- @persistData:'Y' om DBA vill spara utdata i en måltabell, och 'N' om DBA bara vill se utdata direkt.
- @driveDetail:Även om det är valfritt, om du skickar en enhetsbeteckning, kommer parametern @persistData inte att ha någon som helst effekt.
Fält som presenteras och deras betydelse
- enhet: enhetsbeteckningen som innehåller datafiler för den aktuella instansen.
- total_space: storleken på enheten, i GB.
- free_space: mängden GB kvar i enheten.
- used_space: mängden GB som ockuperas av alla databaser i instansen.
- data_insamling_tidsstämpel: synlig endast om 'Y' skickas till @persistData-parametern, och den används för att veta när SP:n kördes och informationen lyckades sparas i tabellen DBA_Storage.
Utförandetester
Jag kommer att demonstrera några exekveringar av den lagrade proceduren så att du kan få en uppfattning om vad du kan förvänta dig av den:
EXEC GetStorageData @persistData = 'N'
Eftersom jag körde detta i en testinstans där jag har allt fyllt i C:\ drive (jag vet, den sämsta övningen någonsin) returnerades bara en rad. Låt mig nu visa dig en skärmdump av användningen av min C:\-enhet, som rapporterats av Windows, bara för att se om SP inte bluffar runt:
Det ser bra ut, för det mesta. Men om du tittar närmare kommer du att märka att "Använt utrymme" i grafiken säger 25GB och SP säger "0.170GB", det är konstigt eller hur? Tja, anledningen är att innebörden i SP är lite annorlunda:här rapporterar den mängden GB som endast upptas av databasfiler, så tänk på det.
Nu verkar den utgången lite torr, eller hur? Jag menar, vi vet inte exakt vad som tar det rapporterade använda utrymmet. Det är där den andra parametern spelar in, så låt oss kolla in den:
EXEC GetStorageData @persistData = 'N', @driveDetail = 'C'
Om du kör det så här får du en lista över specifika databaser som har minst 1 databasfil i enheten som skickas som parameter. Om du summerar kolumnen "totalt utrymme" kommer det att ge dig exakt samma värde som föregående sammanfattade utdata.
Låt mig prova en sak till för att se vad SP ger. Jag ska skapa en ny databas, men jag ska placera databasfilerna i en annan enhet som jag har liggande. Jag kallar databasen för "test" och jag kommer att placera den i enhet S:\.
Så nu matar SP också ut den enheten i resultatuppsättningen. Men återigen, låt oss se vad som händer om vi kastar @driveDetail-parametern med 'S' som ett värde:
Bingo, den rapporterar "testdatabasen" som jag skapade med den storlek jag valde (1 GB för datafilen och 8 MB för transaktionsloggfilen).
Sidofrågor
Nu, för att ge mer värde till DBA, har jag förberett några frågor som kan hjälpa dig att få användbar information från data som finns kvar i tabellen.
*Fråga för att hitta databaser med minst 1 datafil på C:\-enheten.
SELECT * FROM DBA_Storage WHERE drive = 'C:\';
*Fråga för att visualisera listan över enheter sorterade efter free_space, från lägsta till högsta. Med detta kan du veta vilka enheter som behöver din uppmärksamhet så snart som möjligt.
SELECT * FROM DBA_Storage ORDER BY free_space;
*Fråga för att visualisera listan över enheter sorterade efter used_space, från högsta till lägsta. Med detta kan du veta vilka som har mer data än de andra.
SELECT * FROM DBA_Storage ORDER BY used_space DESC;
Här är den fullständiga koden för den lagrade proceduren:
*I början av skriptet kommer du att se standardvärdet som den lagrade proceduren antar om inget värde skickas för varje 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
Slutsats
- Du kan distribuera denna SP i varje SQL Server-instans under din support och implementera en varningsmekanism över hela din stapel med instanser som stöds.
- Om du implementerar ett agentjobb som frågar efter den här informationen relativt ofta, kan du hålla koll på spelet när det gäller att ta stegen för att ta hand om lagringen när vissa trösklar uppfylls, inom din/de miljöer som stöds. .
- Se till att kolla in fler verktyg som publiceras här på CodingSight.