Запрос отчета о распределении дискового пространства и занятого пространства

29

Мы используем в общей сложности 6 баз данных для приложения, и мы можем распределить только 4 ТБ пространства между всеми 6 базами данных автоматического увеличения (через хранилище SAN).

Я хотел бы написать запрос (отчет) для одной базы данных с указанием атрибутов «В настоящее время выделенное пространство» и «Доступное свободное пространство» в разделе «Задачи> Сокращение> База данных» в SQL Server Management Studio.

Затем я хотел бы преобразовать эти числа в ТБ и суммировать каждую базу данных, чтобы получить приблизительную оценку того, сколько места у нас осталось. Можно ли получить доступ к этим полям через запрос T-SQL? Если так, то как будет выглядеть запрос?

Диалог сокращения базы данных

МакГайвер
источник

Ответы:

40

Вот запрос, который Management Studio использует для заполнения этих чисел:

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

Вам нужно выполнить математику здесь, как это делает Management Studio, чтобы получить те же цифры. Кроме того, левое соединение sys.internal_tablesв лучшем случае кажется излишним. Настроив этот запрос, чтобы он соответствовал вашему идеальному результату

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;

С этим обновлением, если ваша база данных не изменится за это время, она должна дать:

753475.94    744030.07    2900.00

Делаем простую математику и выделяем только три числа, которые вы хотите:

;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

Запрос Аарона хорош, но в качестве альтернативы я использую этот запрос из DMV Queries Гленна Берри
(вам нужно изменить математику для 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

Вот несколько SQL, которые могут работать для вас.


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

Это старый SQL, но все еще работает. На днях я собираюсь переписать его, чтобы использовать файлы sys.database_files как ответ от Аарона.

Брюс
источник
7

После работы над похожим вопросом ( запрос истинных физических размеров файлов базы данных ) я думаю, что запрос, который отображает файлы разных размеров, разделенных, например, по журналу и базе данных, и размер файла на диске, был бы более полезным для большинства пользователей.

Это включает в себя размер системного файла и объем занимаемого им места на диске, а также размер файла SQL, используемое пространство SQL и, соответственно, свободное пространство SQL. Включает полный путь оцениваемого файла. Пользователю потребуется изменить вычисление для Size_On_Disk_Bytes, если диск отформатирован с использованием размера выделения, отличного от значения по умолчанию (4096 байт).

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

Кроме того, этот запрос вернет информацию о пространстве на диске тома, на котором размещены файлы. У пользователя должен быть доступ к 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
Джон
источник
Проголосовал за фактическое включение единиц (МБ). Кажется, очень важно включить.
ddunn801
0

Что-то я собрал. Вам нужно POWERSHELL на вашем SQL Server, чтобы запустить это. Не уверен в версии. Это займет ваши размеры дисков и сообщит о размерах файлов и свободного места, а также свободного места на диске.

Он не на 100% оригинален, и его части я нашел в Интернете и собрал все вместе. Это была PITA, чтобы она вписывалась в правильные поля, поэтому вам, возможно, придется поиграть с круглыми скобками.

--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
Alen
источник
0

Нижеприведенный скрипт может быть использован для получения следующей информации: 1. Информация о размере БД 2. FileSpaceInfo 3. AutoGrowth 4. Модель восстановления 5. Информация 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
Винод Нарвал
источник