Nous utilisons 6 bases de données au total pour une application, et nous ne pouvons partager que 4 To d'espace parmi les 6 bases de données à croissance automatique (via SAN).
Je voudrais écrire une requête (rapport) pour une base de données unique indiquant les attributs "Espace actuellement alloué" et "Espace libre disponible" sous l'option Tâches> Rétrécir> Base de données dans SQL Server Management Studio.
Ensuite, je voudrais convertir ces nombres en TB et faire le total de chaque base de données pour obtenir une estimation approximative de l'espace qui nous reste. Ces champs sont-ils accessibles via une requête T-SQL? Si alors, à quoi ressemblerait la requête?
Voici la requête utilisée par Management Studio pour remplir ces nombres:
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
Vous devez effectuer des calculs ici, tout comme Management Studio pour obtenir les mêmes nombres. En outre, la gauche se joint à sys.internal_tables
semble au mieux superflu. Donc, ajustez cette requête pour qu'elle corresponde à votre sortie idéale:
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;
Avec cette mise à jour, en supposant que votre base de données ne change pas entre-temps, elle devrait donner:
753475.94 744030.07 2900.00
Faire des calculs simples et isoler uniquement les trois nombres souhaités:
;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;
La requête d'Aaron est bonne, mais comme alternative, j'utilise cette requête de Glenn Berry DMV Queries
(vous devrez changer les calculs pour les 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);
Voici du SQL qui pourrait vous convenir.
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
C'est du vieux SQL mais ça marche toujours. Un de ces jours, je vais le réécrire pour utiliser les sys.database_files comme la réponse d'Aaron.
Après avoir travaillé sur une question similaire ( Querying True Physical Database File Sizes ), je pense qu'une requête qui affiche les différentes tailles de fichier, séparées, par exemple par journal et base de données, et la taille du fichier sur le disque serait plus utile à la plupart des utilisateurs.
Cela inclut la taille du fichier système et la quantité d'espace qu'il occupe sur le disque, ainsi que la taille du fichier SQL, l'espace SQL utilisé et, par extension, l'espace libre SQL. Il inclut le chemin complet du fichier en cours d'évaluation. Un utilisateur devra modifier le calcul de "Size_On_Disk_Bytes" si le disque est formaté en utilisant une taille d'allocation différente de la valeur par défaut (4096 octets).
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
En outre, cette requête renverra des informations sur l'espace sur le lecteur de volume qui héberge les fichiers. L'utilisateur devra avoir accès à 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
Le script ci-dessous peut être utilisé pour obtenir les informations suivantes: 1. Informations sur la taille de la base de données 2. FileSpaceInfo 3. AutoGrowth 4. Modèle de récupération 5. Informations sur 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
Quelque chose que j'ai mis en place. Vous avez besoin de PowerShell sur votre serveur SQL pour exécuter cela. Pas sûr de la version. Cela prendra la taille de votre lecteur et vous indiquera la taille des fichiers et l'espace libre ainsi que l'espace libre sur le lecteur.
Ce n'est pas 100% original et j'en ai trouvé des parties ailleurs sur Internet et j'ai mis le tout ensemble. C'était un PITA pour le faire rentrer dans les bonnes marges donc vous pourriez avoir à jouer avec les parenthèses
--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