Auflisten von Informationen zu allen Datenbankdateien in SQL Server


89

Ist es möglich, Informationen zu den Dateien (MDF / LDF) aller Datenbanken auf einem SQL Server aufzulisten?

Ich möchte eine Liste erhalten, aus der hervorgeht, welche Datenbank welche Dateien auf der lokalen Festplatte verwendet.

Was ich versucht habe:

  • exec sp_databases alle Datenbanken
  • select * from sys.databases zeigt viele Informationen zu jeder Datenbank an - aber leider werden nicht die von jeder Datenbank verwendeten Dateien angezeigt.
  • select * from sys.database_fileszeigt die mdf / ldf-Dateien der masterDatenbank - aber nicht die anderen Datenbanken

Antworten:


122

Sie können sys.master_files verwenden .

Enthält eine Zeile pro Datei einer Datenbank, wie sie in der Masterdatenbank gespeichert ist. Dies ist eine einzelne systemweite Ansicht.


4
Danke, das (zusammen mit sys.databases) ist das, wonach ich gesucht habe!
M4N

1
Wählen Sie * aus sys.master_files
Cosmin

1
@ M4N Wenn Sie nur den Datenbanknamen erhalten möchten, können Sie auch anrufen, DB_NAME(database_id)anstatt sich mitsys.databases
Cleptus

83

Wenn Sie den Speicherort der Datenbank abrufen möchten, können Sie den Speicherort aller DBs abrufen aktivieren .
Sie können verwenden, sys.master_filesum den Speicherort der Datenbank abzurufen und sys.databseden Datenbanknamen abzurufen

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

Ich verwende ein Skript, um leeren Speicherplatz in jeder Datei zu erhalten:

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

Die Größe wird in KB angegeben.


Was Use [?]soll tun? Es gibt einen Fehler, dass diese gespeicherte Prozedur nicht gefunden werden kann. Beim Entfernen werden die Systemdatenbanken nur mehrmals angezeigt.
Abel

4

Ich habe diese Abfrage erstellt:

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

Sie können dies auch versuchen.

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

3

Ausführen der folgenden SQL (funktioniert nur, wenn Sie nicht mehrere MDF / LDF-Dateien für dieselbe Datenbank haben)

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

gibt diese Ausgabe zurück

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

und Rest der Datenbanken

Wenn Ihre TempDBs mehrere MDFs haben (wie meine), schlägt dieses Skript fehl. Sie können jedoch verwenden

WHERE db.database_id > 4

am Ende und es werden alle Datenbanken außer Systemdatenbanken zurückgegeben.


Mir ist klar, dass es sich um einen kleinen Datensatz handelt, aber das ist kein Grund, korrelierte Unterabfragen zu verwenden. Unter Oracle sind sie möglicherweise in Ordnung, unter SQL Server sind sie jedoch schwerwiegende Leistungskiller, da sie eine zeilenweise Verarbeitung verursachen. Ihr Skript fragt die Tabelle sys.master_files zweimal für jede Zeile in der Tabelle sys.databases ab.
Davos

2
Zusätzlich zu Davos 'Kommentar ... Dieses Skript schlägt auch mit Fehlern fehl, wenn Sie mehrere Datendateien oder Protokolldateien für eine Datenbank haben. (zB Unterabfrage gab mehr als 1 Wert zurück.)
Arkaine55

@Davos Ich weiß, was Sie sagen, aber es hängt davon ab, wie oft Sie diese Abfrage ausführen, da es sich sonst um eine Voroptimierung handelt, die Sie wahrscheinlich nicht benötigen.
adeel41

2
Ich stimme im Allgemeinen zu, dass eine frühe Optimierung schlecht ist, aber ich sage, dass korrelierte Unterabfragen nur ein schlechtes Muster sind, das überhaupt nicht verwendet werden sollte. Es gibt immer Ausnahmen von "nie" -Regeln, aber dies ist keiner dieser Fälle. Ich weiß, dass es geringfügig ist und es hier wirklich keine Rolle spielt, aber das ist nicht der Punkt. Dies ist ein öffentliches Forum, in dem Neulinge bewährte Verfahren erlernen. Daher müssen Sie Vorbildcode bereitstellen.
Davos

1
Die Abfrage schlägt fehl, wenn mehrere Datendateien in einer der Datenbanken verwendet werden. Hier ist eine Version Ihrer Abfrage, die stattdessen Joins verwendet. Prost! SELECT Datenbankname AS DBName, Datenbankdatenbank-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 und mfr ' .master_files mfl ON db.database_id = mfl.database_id AND mfl.type_desc = 'LOG' ORDER BY db.database_id
Robert

2

Mit diesem Skript können Sie alle verwendeten Datenbanknamen und Dateien anzeigen (mit Ausnahme der Systemdatenbanken).

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

1

Dieses Skript listet das meiste auf, wonach Sie suchen, und kann hoffentlich an Ihre Bedürfnisse angepasst werden. Beachten Sie, dass dort eine permanente Tabelle erstellt wird. Möglicherweise möchten Sie diese ändern. Es ist eine Teilmenge eines größeren Skripts, das auch Sicherungs- und Auftragsinformationen auf verschiedenen Servern zusammenfasst.

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] 

Ein ausgezeichnetes Skript, das kopiert / eingefügt und unverändert verwendet werden kann. Eine Frage ist jedoch, dass LogVolumeFreeSpaceMBin meinem Fall 44756 für alle Dateien immer die gleiche Menge angezeigt wird. Ist es möglich, den tatsächlichen freien Speicherplatz zu erhalten? Oder ist das die Anzahl des maximalen freien Speicherplatzes auf dem Laufwerk, auf dem sich die LDF befindet?
Abel

Hallo Abel, es ist eine Weile her, seit ich geschrieben habe und ich bin mir deines Problems nicht wirklich sicher. Es gibt eine Alternative zu XP_FIXEDDRIVES mit dem Namen sys.dm_os_volume_stats, sodass Sie versuchen können, diese zu verwenden. Wenn das Problem darin besteht, dass sich die Dateigrößen der Datenbank im Laufe der Zeit nicht ändern, ist dies normal, da SQL Server einen großen Blob leeren Speicherplatz für seine Verwendung zuweist und diese Datei erst erweitert, wenn sie voll ist. Es wird eine Datei in Sprüngen mit dem Betrag erweitern, der durch die Dateieinstellungen für diese bestimmte Datenbank bestimmt wird
Gerard

0

Die Abfrage schlägt fehl, wenn mehrere Datendateien (z. B. ".ndf" -Dateitypen) in einer der Datenbanken verwendet werden.

Hier ist eine Version Ihrer Abfrage, die Joins anstelle der Unterabfragen verwendet.

Prost!

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

Das folgende Skript kann verwendet werden, um folgende Informationen abzurufen: 1. DB-Größeninfo 2. FileSpaceInfo 3. AutoGrowth 4. Wiederherstellungsmodell 5. Log_reuse_backup-Informationen

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

Ich füge nur meine 2 Cent hinzu.

Wenn Sie speziell danach suchen, den gesamten freien Speicherplatz nur in Datendateien oder nur in Protokolldateien in allen Datenbanken zu finden, können Sie die Spalte "data_space_id" verwenden. 1 steht für Datendateien und 0 für Protokolldateien.

CODE:

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

Wenn Sie Ihre Datenbank umbenennen, benennt MS SQL Server die zugrunde liegenden Dateien nicht um.

Die folgende Abfrage gibt Ihnen den aktuellen Namen der Datenbank und den Namen der logischen Datei (möglicherweise der ursprüngliche Name der Datenbank, als sie erstellt wurde) sowie die entsprechenden physischen Dateinamen.

Hinweis: Deaktivieren Sie die letzte Zeile, um nur die tatsächlichen Datendateien anzuzeigen

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'

Referenz:

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

Sie können Folgendes verwenden:

SP_HELPDB [Master]
GO

Dies liefert nur Informationen für die einzelne angegebene Datenbank. Die Frage ist für ALLE Datenbanken.
Thronk
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.