programing

SQL Server 2008: 모든 데이터베이스 크기를 쿼리하는 방법

muds 2023. 4. 26. 23:46
반응형

SQL Server 2008: 모든 데이터베이스 크기를 쿼리하는 방법

MS SQL 2008 R2, 500개의 데이터베이스를 보유하고 있습니다.모든 데이터베이스 크기를 쿼리하는 가장 효율적이고 쉽고 '현대적인' 방법은 무엇입니까?

출력에는 다음과 같은 열이 있어야 합니다.

  • 데이터베이스 이름
  • 데이터 파일 크기
  • 로그 파일 크기
with fs
as
(
    select database_id, type, size * 8.0 / 1024 size
    from sys.master_files
)
select 
    name,
    (select sum(size) from fs where type = 0 and fs.database_id = db.database_id) DataFileSizeMB,
    (select sum(size) from fs where type = 1 and fs.database_id = db.database_id) LogFileSizeMB
from sys.databases db

효율성이 무엇을 의미하는지 정확히 알 수 없지만, 이는 간단하고 효과적어도 효과가 있습니다.

SELECT
    DB_NAME(db.database_id) DatabaseName,
    (CAST(mfrows.RowSize AS FLOAT)*8)/1024 RowSizeMB,
    (CAST(mflog.LogSize AS FLOAT)*8)/1024 LogSizeMB,
    (CAST(mfstream.StreamSize AS FLOAT)*8)/1024 StreamSizeMB,
    (CAST(mftext.TextIndexSize AS FLOAT)*8)/1024 TextIndexSizeMB
FROM sys.databases db
    LEFT JOIN (SELECT database_id, SUM(size) RowSize FROM sys.master_files WHERE type = 0 GROUP BY database_id, type) mfrows ON mfrows.database_id = db.database_id
    LEFT JOIN (SELECT database_id, SUM(size) LogSize FROM sys.master_files WHERE type = 1 GROUP BY database_id, type) mflog ON mflog.database_id = db.database_id
    LEFT JOIN (SELECT database_id, SUM(size) StreamSize FROM sys.master_files WHERE type = 2 GROUP BY database_id, type) mfstream ON mfstream.database_id = db.database_id
    LEFT JOIN (SELECT database_id, SUM(size) TextIndexSize FROM sys.master_files WHERE type = 4 GROUP BY database_id, type) mftext ON mftext.database_id = db.database_id

다음과 같은 결과:

DatabaseName  RowSizeMB LogSizeMB StreamSizeMB TextIndexSizeMB
------------- --------- --------- ------------ ---------------
master        4         1.25      NULL         NULL
model         2.25      0.75      NULL         NULL
msdb          14.75     8.1875    NULL         NULL
tempdb        8         0.5       NULL         NULL

참고: 이 기사에서 영감을 얻었습니다.

다음은 모든 데이터베이스 및 로그 파일 이름, 크기 및 데이터베이스 상태(예: ONLINE)를 읽기 쉽고 보기 쉬운 출력으로 제공하는 간단하고 빠르고 안정적인 쿼리입니다.

SELECT
    D.name,
    F.Name AS FileType,
    F.physical_name AS PhysicalFile,
    F.state_desc AS OnlineStatus,
    CAST(F.size AS bigint) * 8*1024 AS SizeInBytes,
    CAST((F.size*8.0)/1024/1024 AS decimal(18,3)) AS SizeInGB
FROM 
    sys.master_files F
    INNER JOIN sys.databases D ON D.database_id = F.database_id
ORDER BY SizeInBytes desc

순서가 지정된 총 데이터베이스 크기 설명 포함

SELECT     
DB_NAME(db.database_id) DatabaseName,     
(CAST(mfrows.RowSize AS FLOAT)*8)/1024 RowSizeMB,     
(CAST(mflog.LogSize AS FLOAT)*8)/1024 LogSizeMB, 
(CAST(mfrows.RowSize AS FLOAT)*8)/1024/1024+(CAST(mflog.LogSize AS FLOAT)*8)/1024/1024 DBSizeG,
(CAST(mfstream.StreamSize AS FLOAT)*8)/1024 StreamSizeMB,     
(CAST(mftext.TextIndexSize AS FLOAT)*8)/1024 TextIndexSizeMB 
FROM sys.databases db     
LEFT JOIN (SELECT database_id, 
                  SUM(size) RowSize 
            FROM sys.master_files 
            WHERE type = 0 
            GROUP BY database_id, type) mfrows 
    ON mfrows.database_id = db.database_id     
LEFT JOIN (SELECT database_id, 
                  SUM(size) LogSize 
            FROM sys.master_files 
            WHERE type = 1 
            GROUP BY database_id, type) mflog 
    ON mflog.database_id = db.database_id     
LEFT JOIN (SELECT database_id, 
                  SUM(size) StreamSize 
                  FROM sys.master_files 
                  WHERE type = 2 
                  GROUP BY database_id, type) mfstream 
    ON mfstream.database_id = db.database_id     
LEFT JOIN (SELECT database_id, 
                  SUM(size) TextIndexSize 
                  FROM sys.master_files 
                  WHERE type = 4 
                  GROUP BY database_id, type) mftext 
    ON mftext.database_id = db.database_id 
       ORDER BY 4 DESC

모든 것이 지나치게 복잡해 보입니다!아니면 제가 뭔가를 놓치고 있나요?

다음과 같은 것만 있으면 됩니다.

select d.name, case when m.type = 0 then 'Data' else 'Log' end,  m.size * 8 / 1024
from sys.master_files m JOIN sys.databases d ON d.database_id = m.database_id

또는 로그를 원하지 않는 경우:

select d.name, m.size * 8 / 1024
from sys.master_files m JOIN sys.databases d ON d.database_id = m.database_id and m.type =0
SELECT
    DB.name,
    SUM(CASE WHEN type = 0 THEN MF.size * 8 / 1024 ELSE 0 END) AS DataFileSizeMB,
    SUM(CASE WHEN type = 1 THEN MF.size * 8 / 1024 ELSE 0 END) AS LogFileSizeMB
FROM
    sys.master_files MF
    JOIN sys.databases DB ON DB.database_id = MF.database_id
GROUP BY DB.name
ORDER BY DataFileSizeMB DESC

자세한 내용을 찾거나 아래 링크 https://gallery.technet.microsoft.com/SIZE-OF-ALL-DATABASES-IN-0337f6d5#content 에서 스크립트를 다운로드하십시오.

 DECLARE @spacetable table
 (
 database_name varchar(50) ,
 total_size_data int,
 space_util_data int,
 space_data_left int,
 percent_fill_data float,
 total_size_data_log int,
 space_util_log int,
 space_log_left int,
 percent_fill_log char(50),
 [total db size] int,
 [total size used] int,
 [total size left] int
 )
 insert into  @spacetable
 EXECUTE master.sys.sp_MSforeachdb 'USE [?];
 select x.[DATABASE NAME],x.[total size data],x.[space util],x.[total size data]-x.[space util] [space left data],
 x.[percent fill],y.[total size log],y.[space util],
 y.[total size log]-y.[space util] [space left log],y.[percent fill],
 y.[total size log]+x.[total size data] ''total db size''
 ,x.[space util]+y.[space util] ''total size used'',
 (y.[total size log]+x.[total size data])-(y.[space util]+x.[space util]) ''total size left''
  from (select DB_NAME() ''DATABASE NAME'',
 sum(size*8/1024) ''total size data'',sum(FILEPROPERTY(name,''SpaceUsed'')*8/1024) ''space util''
 ,case when sum(size*8/1024)=0 then ''less than 1% used'' else
 substring(cast((sum(FILEPROPERTY(name,''SpaceUsed''))*1.0*100/sum(size)) as CHAR(50)),1,6) end ''percent fill''
 from sys.master_files where database_id=DB_ID(DB_NAME())  and  type=0
 group by type_desc  ) as x ,
 (select 
 sum(size*8/1024) ''total size log'',sum(FILEPROPERTY(name,''SpaceUsed'')*8/1024) ''space util''
 ,case when sum(size*8/1024)=0 then ''less than 1% used'' else
 substring(cast((sum(FILEPROPERTY(name,''SpaceUsed''))*1.0*100/sum(size)) as CHAR(50)),1,6) end ''percent fill''
 from sys.master_files where database_id=DB_ID(DB_NAME())  and  type=1
 group by type_desc  )y'
 select * from @spacetable
 order by database_name

저는 최근에 이런 것을 찾다가 우연히 이 페이지를 발견했습니다.누군가 이 문제를 발견하고 핵심 사용자 데이터베이스에만 관심이 있는 경우 Master, msdb...를 제외한 이와 같은 것을 사용할 수 있습니다.

SELECT
DB_NAME(db.database_id) DatabaseName,
(CAST(mfrows.RowSize AS FLOAT)*8)/1024 RowSizeMB,
(CAST(mflog.LogSize AS FLOAT)*8)/1024 LogSizeMB
FROM sys.databases db
LEFT JOIN (SELECT database_id, SUM(size) RowSize FROM sys.master_files WHERE type = 0 GROUP BY database_id, type) mfrows ON mfrows.database_id = db.database_id
LEFT JOIN (SELECT database_id, SUM(size) LogSize FROM sys.master_files WHERE type = 1 GROUP BY database_id, type) mflog ON mflog.database_id = db.database_id
where DB_NAME(db.database_id) not like 'master'
and DB_NAME(db.database_id) not like 'msdb'
and DB_NAME(db.database_id) not like 'model'
and DB_NAME(db.database_id) not like 'tempdb'
and DB_NAME(db.database_id) not like 'Northwind'
and DB_NAME(db.database_id) not like 'ReportServer'
order by DB_NAME(db.database_id)
IF OBJECT_ID('tempdb.dbo.#space') IS NOT NULL
    DROP TABLE #space

CREATE TABLE #space (
      database_id INT PRIMARY KEY
    , data_used_size DECIMAL(18,2)
    , log_used_size DECIMAL(18,2)
)

DECLARE @SQL NVARCHAR(MAX)

SELECT @SQL = STUFF((
    SELECT '
    USE [' + d.name + ']
    INSERT INTO #space (database_id, data_used_size, log_used_size)
    SELECT
          DB_ID()
        , SUM(CASE WHEN [type] = 0 THEN space_used END)
        , SUM(CASE WHEN [type] = 1 THEN space_used END)
    FROM (
        SELECT s.[type], space_used = SUM(FILEPROPERTY(s.name, ''SpaceUsed'') * 8. / 1024)
        FROM sys.database_files s
        GROUP BY s.[type]
    ) t;'
    FROM sys.databases d
    WHERE d.[state] = 0
    FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'), 1, 2, '')

EXEC sys.sp_executesql @SQL

SELECT
      d.database_id
    , d.name
    , d.state_desc
    , d.recovery_model_desc
    , t.total_size
    , t.data_size
    , s.data_used_size
    , t.log_size
    , s.log_used_size
FROM (
    SELECT
          database_id
        , log_size = CAST(SUM(CASE WHEN [type] = 1 THEN size END) * 8. / 1024 AS DECIMAL(18,2))
        , data_size = CAST(SUM(CASE WHEN [type] = 0 THEN size END) * 8. / 1024 AS DECIMAL(18,2))
        , total_size = CAST(SUM(size) * 8. / 1024 AS DECIMAL(18,2))
    FROM sys.master_files
    GROUP BY database_id
) t
JOIN sys.databases d ON d.database_id = t.database_id
LEFT JOIN #space s ON d.database_id = s.database_id
ORDER BY t.total_size DESC

답변을 가로채서 포인트나 다른 것에 맞게 조정하는 것이 아니라, 여기 또 다른 인수분해가 있습니다.

select d.name, 
    sum(m0.size*8.0/1024) data_file_size_mb, 
    sum(m1.size*8.0/1024) log_file_size_mb 
from sys.databases d
inner join sys.master_files m0 on m0.database_id = d.database_id
inner join sys.master_files m1 on m1.database_id = d.database_id
where m0.type = 0 and m1.type = 1
group by d.name, d.database_id
order by d.database_id

단순화 및 개선된 버전:

SELECT
    D.name,
    CAST(SUM(F.size) AS bigint) * 8*1024 AS SizeInBytes,
    CAST(SUM(F.size*8.0)/1024/1024 AS decimal(18,3)) AS SizeInGB
FROM 
    sys.master_files F
    INNER JOIN sys.databases D ON D.database_id = F.database_id
GROUP BY D.name
ORDER BY SizeInBytes desc

더 좋고 꽤 간단한 것.

SELECT [Database Name] = DB_NAME(database_id),
     [Type] = CASE WHEN Type_Desc = 'ROWS' THEN 'Data File(s)'
               WHEN Type_Desc = 'LOG'  THEN 'Log File(s)'
               ELSE Type_Desc END,
     [Size in MB] = CAST( ((SUM(Size)* 8) / 1024.0) AS DECIMAL(18,2) )
FROM   sys.master_files
--Uncomment if you need to query for a particular database
--WHERE      database_id = DB_ID(‘Database Name’) 
GROUP BY  GROUPING SETS
        (
               (DB_NAME(database_id), Type_Desc),
               (DB_NAME(database_id))
        ) ORDER BY      DB_NAME(database_id), Type_Desc DESC

아래와 같이 데이터 파일과 로그 파일의 크기를 별도로 제공합니다.

DatabaseName    Type            Size in MB
-------------------------------------------
FMS             Data File(s)    23.00
FMS             Log File(s)     1.50
PointOfSale     Data File(s)    4.00
PointOfSale     Log File(s)     1.25
Union2          Data File(s)    336.00
Union2          Log File(s)     1191.13
SurveyProject   Data File(s)    4.00
SurveyProject   Log File(s)     1.00

다음 코드는 저에게 매우 잘 작동했습니다.

    SELECT
        D.name As DbName,
        F.Name AS FullDbName,
        CASE WHEN F.type_desc='ROWS' THEN 'mdf' ELSE 'ldf' END AS FileType,
        F.physical_name AS PhysicalFile,
        CONVERT(DATE,D.create_date) AS CreationDate,
        F.state_desc AS OnlineStatus,
        CAST((F.size*8)/1024 AS VARCHAR(26)) + ' MB' AS FileSize_MB,
        CAST(F.size*8 AS VARCHAR(32)) + ' Bytes' AS FileSize_Bytes,
        CAST(CAST(ROUND((F.size*8)/(1024.0*1024.0),0) AS INT) AS VARCHAR(32)) + ' GB' AS FileSize_GB

    FROM 
        sys.master_files F
        INNER JOIN sys.databases D ON D.database_id = F.database_id

    ORDER BY
         D.name 

이 모든 예제는 대부분의 데이터베이스 서버에서 잘 작동합니다.그러나 인스턴스가 여러 개인 서버가 하나 있고 이러한 서버가 모두 있는 경우 이러한 쿼리는 결과를 제공하지 않습니다.

예를 들어 첫 번째 쿼리는 다음과 같은 결과를 제공합니다.

name    DataFileSizeMB  LogFileSizeMB
master  NULL    NULL
tempdb  NULL    NULL
model   NULL    NULL
msdb    NULL    NULL

따라서 데이터베이스는 다음에서 선택됩니다.sys.databases어찌 되었든sys.master_files비어 있거나 결과가 없는 것 같습니다.

단순한 쿼리도select * from sys.master_files0개의 레코드 결과가 있습니다.오류는 수신되지 않지만 레코드는 발견되지 않습니다.데이터베이스 인스턴스가 하나뿐인 서버에서는 이 작업이 정상적으로 수행됩니다.

때때로 보안 문제로 인해 모든 DB를 요청할 수 없으며 DB 접두사를 사용하여 하나씩 쿼리해야 합니다. 이 경우 동적 쿼리를 만들었습니다.

go
declare @Results table ([Name] nvarchar(max), [DataFileSizeMB] int, [LogFileSizeMB] int);

declare @QaQuery nvarchar(max)
declare @name nvarchar(max)

declare MY_CURSOR cursor 
  local static read_only forward_only
for 
select name from master.dbo.sysdatabases where name not in ('master', 'tempdb', 'model', 'msdb', 'rdsadmin');

open MY_CURSOR
fetch next from MY_CURSOR into @name
while @@FETCH_STATUS = 0
begin 
    if(len(@name)>0)
    begin
        print @name + ' Column Exist'
        set @QaQuery = N'select 
                            '''+@name+''' as Name
                            ,sum(case when type = 0 then size else 0 end) as DataFileSizeMB
                            ,sum(case when type = 1 then size else 0 end) as LogFileSizeMB
                        from ['+@name+'].sys.database_files
                        group by replace(name, ''_log'', '''')';

        insert @Results exec sp_executesql @QaQuery;
    end
  fetch next from MY_CURSOR into @name
end
close MY_CURSOR
deallocate MY_CURSOR

select * from @Results order by DataFileSizeMB desc
go

언급URL : https://stackoverflow.com/questions/5945360/sql-server-2008-how-to-query-all-databases-sizes

반응형