Interrogazione per segnalare l'allocazione dello spazio su disco e lo spazio utilizzato


29

Stiamo utilizzando 6 database in totale per un'applicazione e possiamo condividere solo 4 TB di spazio tra tutti e 6 i database a crescita automatica (tramite l'archiviazione SAN).

Vorrei scrivere una query (report) per un singolo database indicando gli attributi "Spazio attualmente allocato" e "Spazio disponibile disponibile" sotto l'opzione Attività> Riduci> Database in SQL Server Management Studio.

Quindi vorrei convertire quei numeri in TB e sommare ogni database per ottenere una stima approssimativa di quanto spazio ci rimane. È possibile accedere a questi campi tramite una query T-SQL? In tal caso, come sarebbe la query?

Finestra di dialogo Riduci database

Risposte:


40

Ecco la query che Management Studio utilizza per popolare quei numeri:

SELECT
(SELECT SUM(CAST(df.size as float)) FROM sys.database_files AS df 
   WHERE df.type in ( 0, 2, 4 ) ) AS [DbSize],
SUM(a.total_pages) AS [SpaceUsed],
(SELECT SUM(CAST(df.size as float)) FROM sys.database_files AS df 
   WHERE df.type in (1, 3)) AS [LogSize]
FROM
sys.partitions p join sys.allocation_units a 
  on p.partition_id = a.container_id 
left join sys.internal_tables it 
  on p.object_id = it.object_id

È necessario eseguire la matematica qui come fa Management Studio per ottenere gli stessi numeri. Inoltre, il join sinistro sys.internal_tablessembra al massimo superfluo. Quindi regolando la query in modo che corrisponda all'output ideale:

SELECT
(SELECT CONVERT(DECIMAL(18,2), SUM(CAST(df.size as float))*8/1024.0)
   FROM sys.database_files AS df 
   WHERE df.type in ( 0, 2, 4 ) ) AS [DbSize],
CONVERT(DECIMAL(18,2), SUM(a.total_pages)*8/1024.0) AS [SpaceUsed],
(SELECT CONVERT(DECIMAL(18,2), SUM(CAST(df.size as float))*8/1024.0)
   FROM sys.database_files AS df 
   WHERE df.type in (1, 3)) AS [LogSize]
FROM sys.partitions p join sys.allocation_units a 
  on p.partition_id = a.container_id;

Con questo aggiornamento, supponendo che il tuo database non cambi nel frattempo, dovrebbe produrre:

753475.94    744030.07    2900.00

Fare un po 'di matematica semplice e isolare solo i tre numeri desiderati:

;WITH t(s) AS
(
  SELECT CONVERT(DECIMAL(18,2), SUM(size)*8/1024.0)
   FROM sys.database_files
   WHERE [type] % 2 = 0
), 
d(s) AS
(
  SELECT CONVERT(DECIMAL(18,2), SUM(total_pages)*8/1024.0)
   FROM sys.partitions AS p
   INNER JOIN sys.allocation_units AS a 
   ON p.[partition_id] = a.container_id
)
SELECT 
  Allocated_Space = t.s, 
  Available_Space = t.s - d.s,
  [Available_%] = CONVERT(DECIMAL(5,2), (t.s - d.s)*100.0/t.s)
FROM t CROSS APPLY d;

24

La query di Aaron è buona, ma in alternativa, utilizzo questa query dalle query DMV di Glenn Berry
(dovresti cambiare la matematica per i TB):

-- Individual File Sizes and space available for current database
-- (Query 36) (File Sizes and Space)
SELECT f.name AS [File Name] , f.physical_name AS [Physical Name], 
CAST((f.size/128.0) AS DECIMAL(15,2)) AS [Total Size in MB],
CAST(f.size/128.0 - CAST(FILEPROPERTY(f.name, 'SpaceUsed') AS int)/128.0 AS DECIMAL(15,2)) 
AS [Available Space In MB], [file_id], fg.name AS [Filegroup Name]
FROM sys.database_files AS f WITH (NOLOCK) 
LEFT OUTER JOIN sys.data_spaces AS fg WITH (NOLOCK) 
ON f.data_space_id = fg.data_space_id OPTION (RECOMPILE);

9

Ecco alcuni SQL che potrebbero funzionare per te.


Create Table #dbInfo (dId smallint, dbName sysname, gId smallint NULL, segName varchar(256) NULL, 
       filName varchar(520) NULL, sizeMg decimal(10,2) null, 
       usedMg decimal(10,2) null, freeMg decimal(10,2) null, 
       pcntUsed decimal(10,2) null, pcntFree decimal(10,2) null)
Declare @sSql varchar(1000)
Set @sSql = 'Use [?];
Insert #dbInfo (dId, dbName, gid, segName, filName, sizeMg, usedMg)
Select db_id(), db_name(), groupid, rtrim(name), filename, Cast(size/128.0 As Decimal(10,2)), 
Cast(Fileproperty(name, ''SpaceUsed'')/128.0 As Decimal(10,2))
From dbo.sysfiles Order By groupId Desc;'
Exec sp_MSforeachdb @sSql
Update #dbInfo Set
freeMg = sizeMg - usedMg,
pcntUsed = (usedMg/sizeMg)*100,
pcntFree = ((sizeMg-usedMg)/sizeMg)*100

select * from #dbInfo compute sum(sizeMG),  sum(FreeMg) 
drop table #dbInfo

È vecchio SQL ma funziona ancora. Uno di questi giorni lo riscriverò per usare i file sys.database_ come la risposta di Aaron.


7

Dopo aver lavorato su una domanda simile ( Interrogazione delle dimensioni dei file del database fisico reale ), penso che una query che mostri le diverse dimensioni dei file, separate, ad esempio da registro e database, e le dimensioni del file su disco sarebbero più utili per la maggior parte degli utenti.

Ciò include la dimensione del file di sistema e la quantità di spazio che occupa sul disco, nonché la dimensione del file SQL, lo spazio SQL utilizzato e, per estensione, anche lo spazio libero SQL. Include il percorso completo del file in fase di valutazione. Un utente dovrebbe modificare il calcolo per "Size_On_Disk_Bytes" se il disco è formattato utilizzando una dimensione di allocazione diversa da quella predefinita (4096 byte).

SELECT fg.data_space_id AS FGID,
   (f.file_id) AS File_Id,
   -- As provided by OP, size on disk in bytes.
   REPLACE(CONVERT(VARCHAR,CONVERT(MONEY, CAST(f.size AS FLOAT) * 8.00 * 1024), 1), '.00','') AS Size_On_Disk_Bytes,
   ROUND((CAST(f.size AS FLOAT) * 8.00/1024)/1024,3) AS Actual_File_Size,
   ROUND(CAST((f.size) AS FLOAT)/128,2) AS Reserved_MB,
   ROUND(CAST((FILEPROPERTY(f.name,'SpaceUsed')) AS FLOAT)/128,2) AS Used_MB,
   ROUND((CAST((f.size) AS FLOAT)/128)-(CAST((FILEPROPERTY(f.name,'SpaceUsed'))AS FLOAT)/128),2) AS Free_MB,
   f.name,
   f.physical_name
FROM sys.database_files f 
    LEFT JOIN sys.filegroups fg
    ON f.data_space_id = fg.data_space_id

Inoltre, questa query restituirà informazioni sullo spazio nell'unità di volume che ospita i file. L'utente dovrà avere accesso a sys.master_files.

SELECT DISTINCT dovs.logical_volume_name AS LogicalName,
dovs.volume_mount_point AS Drive,
CONVERT(INT,dovs.available_bytes/1048576.0) AS FreeSpaceInMB
FROM sys.master_files mf
CROSS APPLY sys.dm_os_volume_stats(mf.database_id, mf.FILE_ID) dovs
ORDER BY FreeSpaceInMB ASC

Eseguito l'upgrade per l'inclusione effettiva delle unità (MB). Sembra abbastanza importante da includere.
ddunn801

0

Qualcosa che ho messo insieme. Hai bisogno di POWERSHELL sul tuo SQL Server per eseguire questo. Non sono sicuro della versione. In questo modo le dimensioni dell'unità verranno riportate e verranno riportate le dimensioni del file e lo spazio libero, nonché lo spazio libero sull'unità.

Non è originale al 100% e parti di esso l'ho trovato altrove su Internet e ho messo tutto insieme. È stato un PITA adattarlo ai margini giusti, quindi potresti dover giocare con le parentesi

--drop table ##DB_FILE_INFO
 --alter procedure super_drive_info3 

 --as

  if exists ( select * from tempdb.dbo.sysobjects o
    where o.xtype in ('U') and o.name in ('##DB_FILE_INFO' ))
drop table ##DB_FILE_INFO

if exists ( select * from tempdb.dbo.sysobjects o
    where o.xtype in ('U') and o.name in ('##output'))
drop table ##output

 create table ##DB_FILE_INFO (
[server_Name] varchar(255) not null,
[database_name] varchar(255) not null,
[File_ID]           int     not null,
[File_Type]     int     not null ,
[Drive]     varchar(255)    not null ,
[Logical_Name]      varchar(255)    not null ,
[Physical_Name]     varchar(255)    not null ,
[FILE_SIZE_MB]      int     not null ,
[SPace_USED_MB] int     not null ,
[Free_space]    int     not null ,
[Max_SIZE]      int     not null ,
[Percent_Log_growth_enabled]    int     not null ,
[growth_rate]   int     not null ,
[current_date]      datetime        not null
)
--go
declare @sql    nvarchar(4000)
set @sql =
'use ['+'?'+']
 --if db_name() <> N''?'' goto Error_Exit
 insert into ##DB_FILE_INFO
(
    [server_Name],
    [database_name],
    [File_ID],
[File_Type],
[Drive],
[Logical_Name],
[Physical_Name],
[FILE_SIZE_MB],
[SPace_USED_MB],
[Free_space],
[Max_SIZE],
[Percent_Log_growth_enabled],
[growth_rate],
[current_date]
)
SELECT 
@@servername as [Server_Name],
db_name() as database_name,
[file_id] AS [File_ID],
[type] AS [File_Type],
substring([physical_name],1,1) AS [Drive],
[name] AS [Logical_Name],
[physical_name] AS [Physical_Name],
CAST([size] as DECIMAL(38,0))/128. AS [File Size MB], 
CAST(FILEPROPERTY([name],''SpaceUsed'') AS DECIMAL(38,0))/128. AS 
[Space_Used_MB], 
(CAST([size] AS DECIMAL(38,0))/128) - 
(CAST(FILEPROPERTY([name],''SpaceUsed'') AS DECIMAL(38,0))/128.) AS [Free 
 Space],
[max_size] AS [Max_Size],
[is_percent_growth] AS [Percent_Growth_Enabled],
[growth] AS [Growth Rate],
getdate() AS [Current_Date]
FROM sys.database_files'
 exec sp_msforeachdb @sql
 declare @svrName varchar(255)
declare @sql2 varchar(400)
--by default it will take the current server name, we can the set the server 
name as well
set @svrName = @@SERVERNAME
set @sql2 = 'powershell.exe -c "Get-WmiObject -ComputerName ' + 
QUOTENAME(@svrName,'''') + ' -Class Win32_Volume -Filter ''DriveType = 3'' | 
select name,capacity,freespace | 

foreach{$_.name+''|
 ''+$_.capacity/1048576+''%''+$_.freespace/1048576+''*''}"'
 --creating a temporary table
 CREATE TABLE ##output
 (line varchar(255))
 --inserting  in to temporary table
 insert ##output
 EXEC xp_cmdshell @sql2;

 with Output2 
 --(drivename, capacity(gb),freespace(gb), always_on_status)
 as
 (
 select @@servername as server_name, 
rtrim(ltrim(SUBSTRING(line,1,CHARINDEX(':',line) -1))) as drivename
 ,round(cast(rtrim(ltrim(SUBSTRING(line,CHARINDEX('|',line)+1,
 (CHARINDEX('%',line) -1)-CHARINDEX('|',line)) )) as float)/1024,2) as 
 'capacityGB'
 ,round(cast(rtrim(ltrim(SUBSTRING(line,CHARINDEX('%',line)+1,
 (CHARINDEX('*',line) -1)-CHARINDEX('%',line)) )) as float) /1024 ,2)as 
 'freespaceGB'
 ,CASE WHEN (SERVERPROPERTY ('IsHadrEnabled')=1) THEN 'YES' WHEN 
 (SERVERPROPERTY ('IsHadrEnabled')=0) THEN 'NO'ELSE 'NOT AVAILABLE' END AS 
 ALWAYS_ON_STATUS
  --into #output2
 from ##output
   where line like '[A-Z][:]%'
   --order by drivename
  ),
  DB_FILE_INFO2 as
 (
 select server_Name,
    database_name,
    File_ID,
File_Type,
Drive,
Logical_Name,
Physical_Name,
FILE_SIZE_MB,
SPace_USED_MB,
Free_space,
Max_SIZE,
Percent_Log_growth_enabled,
growth_rate
--current_date 
from ##DB_FILE_INFO 
--inner join #output b on a.drive = b.drivename and a.server_Name = 
b.server_name
)
select  
getdate() as Today_Date,
a.server_Name,
a.database_name,
a.Drive,
a.Logical_Name,
a.Physical_Name,
a.FILE_SIZE_MB,
a.Space_Used_MB,
--sum(a.SPace_USED_MB) as hg,
a.Free_space as Free_Space_in_File,
 --Percentage_file_free = (a.Space_Used_MB/a.FILE_SIZE_MB),
b.capacitygb as Total_Drive_capacity,
b.freespacegb as Total_Free_Space,
c.total_log_size_mb,
c.active_log_size_mb
--,Percentage_free_space = ((cast(Free_space as decimal))/(cast(FILE_SIZE_MB 
as decimal)) * 100)

from DB_FILE_INFO2 a
inner join output2 b on a.server_Name = b.server_name and a.Drive = 
 b.drivename
cross apply sys.dm_db_log_stats (db_id(a.database_name)) c
order by a.Drive, a.database_name

--drop table ##DB_FILE_INFO
--drop table #output

0

Lo script seguente può essere utilizzato per ottenere le seguenti informazioni: 1. Informazioni sulla dimensione del database 2. FileSpaceInfo 3. AutoGrowth 4. Modello di recupero 5. Informazioni Log_reuse_backup

CREATE TABLE #tempFileInformation
(
DBNAME          NVARCHAR(256),
[FILENAME]      NVARCHAR(256),
[TYPE]          NVARCHAR(120),
FILEGROUPNAME   NVARCHAR(120),
FILE_LOCATION   NVARCHAR(500),
FILESIZE_MB     DECIMAL(10,2),
USEDSPACE_MB    DECIMAL(10,2),
FREESPACE_MB    DECIMAL(10,2),
AUTOGROW_STATUS NVARCHAR(100)
)
GO

DECLARE @SQL VARCHAR(2000)

SELECT @SQL = '
 USE [?]
            INSERT INTO #tempFileInformation
            SELECT  
                DBNAME          =DB_NAME(),     
                [FILENAME]      =A.NAME,
                [TYPE]          = A.TYPE_DESC,
                FILEGROUPNAME   = fg.name,
                FILE_LOCATION   =a.PHYSICAL_NAME,
                FILESIZE_MB     = CONVERT(DECIMAL(10,2),A.SIZE/128.0),
                USEDSPACE_MB    = CONVERT(DECIMAL(10,2),(A.SIZE/128.0 - ((A.SIZE - CAST(FILEPROPERTY(A.NAME,''SPACEUSED'') AS INT))/128.0))),
                FREESPACE_MB    = CONVERT(DECIMAL(10,2),(A.SIZE/128.0 -  CAST(FILEPROPERTY(A.NAME,''SPACEUSED'') AS INT)/128.0)),
                AUTOGROW_STATUS = ''BY '' +CASE is_percent_growth when 0 then cast (growth/128 as varchar(10))+ '' MB - ''
                                                                  when 1 then cast (growth as varchar(10)) + ''% - '' ELSE '''' END
                                                                  + CASE MAX_SIZE WHEN 0 THEN '' DISABLED '' 
                                                                                  WHEN -1 THEN '' UNRESTRICTED''
                                                                                  ELSE '' RESTRICTED TO '' + CAST(MAX_SIZE/(128*1024) AS VARCHAR(10)) + '' GB '' END
                                                                + CASE IS_PERCENT_GROWTH WHEn 1 then '' [autogrowth by percent]'' else '''' end
    from sys.database_files A
    left join sys.filegroups fg on a.data_space_id = fg.data_space_id
    order by A.type desc,A.name
    ;
    '

    --print @sql

    EXEC sp_MSforeachdb @SQL
    go

    SELECT dbSize.*,fg.*,d.log_reuse_wait_desc,d.recovery_model_desc
    FROM #tempFileInformation fg
    LEFT JOIN sys.databases d on fg.DBNAME = d.name
    CROSS APPLY
    (
        select dbname,
                sum(FILESIZE_MB) as [totalDBSize_MB],
                sum(FREESPACE_MB) as [DB_Free_Space_Size_MB],
                sum(USEDSPACE_MB) as [DB_Used_Space_Size_MB]
            from #tempFileInformation
            where  dbname = fg.dbname
            group by dbname
    )dbSize


go
DROP TABLE #tempFileInformation
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.