Перелік інформації про всі файли баз даних у SQL Server


90

Чи можна перерахувати інформацію про файли (MDF / LDF) усіх баз даних на SQL Server?

Я хотів би отримати список, який показує, яка база даних використовує які файли на локальному диску.

Що я спробував:

  • exec sp_databases усі бази даних
  • select * from sys.databases показує багато інформації про кожну базу даних - але, на жаль, вона не відображає файли, що використовуються кожною базою даних.
  • select * from sys.database_filesпоказує файли mdf / ldf masterбази даних, але не інші бази даних

Відповіді:


123

Ви можете використовувати sys.master_files .

Містить рядок на файл бази даних, який зберігається у головній базі даних. Це єдиний загальносистемний погляд.


4
Дякую, це (приєднався до sys.databases) - це те, що я шукав!
M4N

1
select * from sys.master_files
Cosmin

2
@ M4N Якщо ви просто хочете отримати ім'я бази даних, ви можете також зателефонувати DB_NAME(database_id)замість того, щоб приєднатися доsys.databases
Cleptus

84

Якщо ви хочете отримати місцезнаходження бази даних, ви можете поставити прапорець Отримати розташування всіх БД .
Ви можете використовувати sys.master_filesдля отримання розташування db та sys.databseдля отримання імені db

SELECT
    db.name AS DBName,
    type_desc AS FileType,
    Physical_Name AS Location
FROM
    sys.master_files mf
INNER JOIN 
    sys.databases db ON db.database_id = mf.database_id

18

Я використовую скрипт, щоб отримати порожній простір у кожному файлі:

Create Table ##temp
(
    DatabaseName sysname,
    Name sysname,
    physical_name nvarchar(500),
    size decimal (18,2),
    FreeSpace decimal (18,2)
)   
Exec sp_msforeachdb '
Use [?];
Insert Into ##temp (DatabaseName, Name, physical_name, Size, FreeSpace)
    Select DB_NAME() AS [DatabaseName], Name,  physical_name,
    Cast(Cast(Round(cast(size as decimal) * 8.0/1024.0,2) as decimal(18,2)) as nvarchar) Size,
    Cast(Cast(Round(cast(size as decimal) * 8.0/1024.0,2) as decimal(18,2)) -
        Cast(FILEPROPERTY(name, ''SpaceUsed'') * 8.0/1024.0 as decimal(18,2)) as nvarchar) As FreeSpace
    From sys.database_files
'
Select * From ##temp
drop table ##temp

Розмір виражається в КБ.


Що Use [?]слід робити? Це видає помилку, що не може знайти цю збережену процедуру. Видалення показує лише кілька разів системних баз даних.
Абель

4

Я створив цей запит:

SELECT 
    db.name AS                                   [Database Name], 
    mf.name AS                                   [Logical Name], 
    mf.type_desc AS                              [File Type], 
    mf.physical_name AS                          [Path], 
    CAST(
        (mf.Size * 8
        ) / 1024.0 AS DECIMAL(18, 1)) AS         [Initial Size (MB)], 
    'By '+IIF(
            mf.is_percent_growth = 1, CAST(mf.growth AS VARCHAR(10))+'%', CONVERT(VARCHAR(30), CAST(
        (mf.growth * 8
        ) / 1024.0 AS DECIMAL(18, 1)))+' MB') AS [Autogrowth], 
    IIF(mf.max_size = 0, 'No growth is allowed', IIF(mf.max_size = -1, 'Unlimited', CAST(
        (
                CAST(mf.max_size AS BIGINT) * 8
        ) / 1024 AS VARCHAR(30))+' MB')) AS      [MaximumSize]
FROM 
     sys.master_files AS mf
     INNER JOIN sys.databases AS db ON
            db.database_id = mf.database_id

3

Ви також можете спробувати це.

 select db_name(dbid) dbname, filename from sys.sysaltfiles

3

Виконання наступного sql (це буде працювати лише тоді, коли у вас немає декількох файлів mdf / ldf для однієї бази даних)

SELECT
    db.name AS DBName,
    (select mf.Physical_Name FROM sys.master_files mf where mf.type_desc = 'ROWS' and db.database_id = mf.database_id ) as DataFile,
    (select mf.Physical_Name FROM sys.master_files mf where mf.type_desc = 'LOG' and db.database_id = mf.database_id ) as LogFile
FROM sys.databases db

поверне цей результат

DBName       DataFile                     LogFile
--------------------------------------------------------------------------------
master       C:\....\master.mdf           C:\....\mastlog.ldf
tempdb       C:\....\tempdb.mdf           C:\....\templog.ldf
model        C:\....\model.mdf            C:\....\modellog.ldf

та інші бази даних

Якщо у ваших TempDB є кілька MDF (як у мене), цей сценарій не вдасться. Однак можна використовувати

WHERE db.database_id > 4

в кінці, і він поверне всі бази даних, крім системних.


Я усвідомлюю, що це невеликий набір даних, але це не причина використовувати корельовані підзапити. З Oracle їм може бути добре, але вони є серйозними вбивцями продуктивності на SQL Server, оскільки вони спричиняють обробку рядків за рядком. Ваш скрипт двічі запитує таблицю sys.master_files для кожного рядка в таблиці sys.databases.
Давос,

2
На додаток до коментаря Давоса ... Цей сценарій також не зможе помилитися, якщо у вас є кілька файлів даних або журналів для будь-якої бази даних. (наприклад, підзапит повернув більше 1 значення.)
Arkaine55

@Davos Я знаю, що ви говорите, але це залежить від того, як часто ви виконуєте цей запит, інакше це попередня оптимізація, яка, ймовірно, вам не потрібна.
adeel41

2
Я загалом погоджуюсь з тим, що рання оптимізація - це погано, але я кажу про те, що корельовані підзапити - це просто погана модель, яку ніколи не слід використовувати. Завжди є винятки з правил "ніколи", але це не один із таких випадків. Я знаю, що це незначно, і це може насправді тут не мати значення, але справа не в цьому. Це публічний форум, який новачки використовують для засвоєння гарних практик, тому вам потрібно надати код зразка для наслідування.
Давос

1
Запит помилиться, якщо в одній з баз даних використовується кілька файлів даних. Ось версія вашого запиту, використовуючи натомість об’єднання. На здоров’я! ВИБЕРІТЕ db.name AS DBName, db.database_id, mfr.Physical_Name AS DataFile, mfl.Physical_Name AS LogFile FROM sys.databases db JOIN sys.master_files mfr ON db.database_id = mfr.database_id AND mfr.type_desc 'sIN' sRIN .master_files mfl ON db.database_id = mfl.database_id І mfl.type_desc = 'LOG' ЗАМОВИТИ ЗА db.database_id
Роберт

2

За допомогою цього сценарію ви можете показати всі назви баз даних та використовувані файли (за винятком системних баз даних).

select name,physical_name from sys.master_files where database_id > 4

1

Цей сценарій перелічує більшість із того, що ви шукаєте, і, сподіваємось, його можна змінити відповідно до ваших потреб. Зверніть увагу, що він створює там постійну таблицю - можливо, ви захочете її змінити. Це підмножина більшого сценарію, яка також узагальнює інформацію про резервне копіювання та завдання на різних серверах.

IF OBJECT_ID('tempdb..#DriveInfo') IS NOT NULL
 DROP TABLE #DriveInfo
CREATE TABLE #DriveInfo
 (
    Drive CHAR(1)
    ,MBFree INT
 ) 

INSERT  INTO #DriveInfo
      EXEC master..xp_fixeddrives


IF OBJECT_ID('[dbo].[Tmp_tblDatabaseInfo]', 'U') IS NOT NULL 
   DROP TABLE [dbo].[Tmp_tblDatabaseInfo]
CREATE TABLE [dbo].[Tmp_tblDatabaseInfo](
      [ServerName] [nvarchar](128) NULL
      ,[DBName] [nvarchar](128)  NULL
      ,[database_id] [int] NULL
      ,[create_date] datetime NULL
      ,[CompatibilityLevel] [int] NULL
      ,[collation_name] [nvarchar](128) NULL
      ,[state_desc] [nvarchar](60) NULL
      ,[recovery_model_desc] [nvarchar](60) NULL
      ,[DataFileLocations] [nvarchar](4000)
      ,[DataFilesMB] money null
      ,DataVolumeFreeSpaceMB INT NULL
      ,[LogFileLocations] [nvarchar](4000)
      ,[LogFilesMB] money null
      ,LogVolumeFreeSpaceMB INT NULL

) ON [PRIMARY]

INSERT INTO [dbo].[Tmp_tblDatabaseInfo] 
SELECT 
      @@SERVERNAME AS [ServerName] 
      ,d.name AS DBName 
      ,d.database_id
      ,d.create_date
      ,d.compatibility_level  
      ,CAST(d.collation_name AS [nvarchar](128)) AS collation_name
      ,d.[state_desc]
      ,d.recovery_model_desc
      ,(select physical_name + ' | ' AS [text()]
         from sys.master_files m
         WHERE m.type = 0 and m.database_id = d.database_id
         ORDER BY file_id
         FOR XML PATH ('')) AS DataFileLocations
      ,(select sum(size) from sys.master_files m WHERE m.type = 0 and m.database_id = d.database_id)  AS DataFilesMB
      ,NULL
      ,(select physical_name + ' | ' AS [text()]
         from sys.master_files m
         WHERE m.type = 1 and m.database_id = d.database_id
         ORDER BY file_id
         FOR XML PATH ('')) AS LogFileLocations
      ,(select sum(size) from sys.master_files m WHERE m.type = 1 and m.database_id = d.database_id)  AS LogFilesMB
      ,NULL
FROM  sys.databases d  

WHERE d.database_id > 4 --Exclude basic system databases
UPDATE [dbo].[Tmp_tblDatabaseInfo] 
   SET DataFileLocations = 
      CASE WHEN LEN(DataFileLocations) > 4 THEN  LEFT(DataFileLocations,LEN(DataFileLocations)-2) ELSE NULL END
   ,LogFileLocations =
      CASE WHEN LEN(LogFileLocations) > 4 THEN  LEFT(LogFileLocations,LEN(LogFileLocations)-2) ELSE NULL END
   ,DataFilesMB = 
      CASE WHEN DataFilesMB > 0 THEN  DataFilesMB * 8 / 1024.0   ELSE NULL END
   ,LogFilesMB = 
      CASE WHEN LogFilesMB > 0 THEN  LogFilesMB * 8 / 1024.0  ELSE NULL END
   ,DataVolumeFreeSpaceMB = 
      (SELECT MBFree FROM #DriveInfo WHERE Drive = LEFT( DataFileLocations,1))
   ,LogVolumeFreeSpaceMB = 
      (SELECT MBFree FROM #DriveInfo WHERE Drive = LEFT( LogFileLocations,1))

select * from [dbo].[Tmp_tblDatabaseInfo] 

Відмінний сценарій, який можна скопіювати / вставити та використовувати як є. Хоча одне питання, я бачу, що для LogVolumeFreeSpaceMBнього завжди відображається однакова кількість для всіх файлів, у моєму випадку 44756. Чи можна отримати фактично вільний простір? Або це максимальна кількість вільного місця на диску, де знаходиться LDF?
Абель

Привіт, Абеле! Минув деякий час з того часу, як я писав, і я не дуже впевнений у вашій проблемі. Існує альтернатива XP_FIXEDDRIVES, яка називається sys.dm_os_volume_stats, тому ви можете спробувати використовувати її. Якщо проблема полягає в тому, що розміри файлів бази даних не змінюються з часом, це нормально, оскільки SQL Server виділяє для його використання велику крапку порожнього дискового простору, а потім не розширює цей файл, поки він не буде заповнений. Він буде розширювати файл стрибками із сумою, визначеною налаштуваннями файлу для цієї конкретної бази даних
Джерард

0

Запит буде помилковим, якщо в одній з баз даних використовується декілька файлів даних (наприклад, типи файлів ".ndf").

Ось версія вашого запиту із використанням об’єднань замість підзапитів.

На здоров’я!

SELECT
    db.name AS DBName,
    db.database_id,
    mfr.physical_name AS DataFile,
    mfl.physical_name AS LogFile
FROM sys.databases db
    JOIN sys.master_files mfr ON db.database_id=mfr.database_id AND mfr.type_desc='ROWS'
    JOIN sys.master_files mfl ON db.database_id=mfl.database_id AND mfl.type_desc='LOG'
ORDER BY db.database_id

0

Нижче наведений сценарій можна використовувати для отримання такої інформації: 1. Інформація про розмір БД 2. FileSpaceInfo 3. Автозростання 4. Модель відновлення 5. Інформація про реєстрацію_резервного копіювання

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

0

просто додавши мої 2 центи.

якщо спеціально хочеться знайти загальний вільний простір лише у файлах даних або лише у файлах журналів у всіх базах даних, ми можемо використовувати стовпець "data_space_id". 1 призначений для файлів даних і 0 для файлів журналів.

КОД:

Create Table ##temp
(
    DatabaseName sysname,
    Name sysname,
    spacetype sysname,
    physical_name nvarchar(500),
    size decimal (18,2),
    FreeSpace decimal (18,2)
)   
Exec sp_msforeachdb '
Use [?];

Insert Into ##temp (DatabaseName, Name,spacetype, physical_name, Size, FreeSpace)
    Select DB_NAME() AS [DatabaseName], Name,   ***data_space_id*** , physical_name,
    Cast(Cast(Round(cast(size as decimal) * 8.0/1024.0,2) as decimal(18,2))/1024 as nvarchar) SizeGB,
    Cast(Cast(Round(cast(size as decimal) * 8.0/1024.0,2)/1024 as decimal(18,2)) -
        Cast(FILEPROPERTY(name, ''SpaceUsed'') * 8.0/1024.0 as decimal(18,2))/1024 as nvarchar) As FreeSpaceGB
    From sys.database_files'


select  
    databasename
    , sum(##temp.FreeSpace) 
from 
    ##temp 
where 
    ##temp.spacetype = 1  
group by 
    DatabaseName

drop table ##temp 


0

Якщо ви перейменуєте свою базу даних, MS SQL Server не перейменовує базові файли.

Наступний запит дає вам поточне ім'я бази даних та ім'я логічного файлу (яке може бути оригінальним ім'ям бази даних при її створенні), а також відповідні імена фізичних файлів.

Примітка. Скасуйте коментарі останнього рядка, щоб побачити лише фактичні файли даних

select  db.database_id, 
        db.name "Database Name", 
        files.name "Logical File Name",
        files.physical_name
from    sys.master_files files 
        join sys.databases db on db.database_id = files.database_id 
--                           and files.type_desc = 'ROWS'

Довідково:

https://docs.microsoft.com/en-us/sql/relational-databases/system-catalog-views/sys-master-files-transact-sql?view=sql-server-ver15

https://docs.microsoft.com/en-us/sql/relational-databases/system-catalog-views/sys-databases-transact-sql?view=sql-server-ver15


-3

Ви можете використовувати наступне:

SP_HELPDB [Master]
GO

Це надає інформацію лише для однієї вказаної бази даних. Питання стосується ВСІХ баз даних.
Тронк
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.