Elenco delle informazioni su tutti i file di database in SQL Server


90

È possibile elencare le informazioni sui file (MDF / LDF) di tutti i database su un server SQL?

Vorrei ottenere un elenco che mostra quale database sta utilizzando i file sul disco locale.

Quello che ho provato:

  • exec sp_databases tutti i database
  • select * from sys.databases mostra molte informazioni su ogni database, ma sfortunatamente non mostra i file utilizzati da ogni database.
  • select * from sys.database_filesmostra i file mdf / ldf del masterdatabase, ma non gli altri database

Risposte:


123

Puoi usare sys.master_files .

Contiene una riga per file di un database come archiviato nel database master. Questa è un'unica vista a livello di sistema.


4
Grazie, quello (unito a sys.databases) è quello che stavo cercando!
M4N

1
seleziona * da sys.master_files
Cosmin

2
@ M4N Se vuoi solo ottenere il nome del database puoi anche chiamare DB_NAME(database_id)invece di sys.databases
unirti

84

Se si desidera ottenere la posizione del database, è possibile selezionare Get All DBs Location .
puoi usare sys.master_filesper ottenere la posizione del db e sys.databseper ottenere il nome del 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

Sto usando lo script per ottenere spazio vuoto in ogni file:

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

La dimensione è espressa in KB.


Cosa Use [?]dovrebbe fare? Dà un errore che non riesce a trovare quella stored procedure. La rimozione mostra solo più volte i database di sistema.
Abel

4

Ho creato questa query:

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

Puoi anche provare questo.

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

3

Esecuzione seguente sql (funzionerà solo quando non si hanno più file mdf / ldf per lo stesso database)

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

restituirà questo output

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

e il resto dei database

Se i tuoi TempDB hanno più MDF (come il mio), questo script fallirà. Tuttavia, puoi usare

WHERE db.database_id > 4

alla fine restituirà tutti i database tranne i database di sistema.


Mi rendo conto che si tratta di un piccolo set di dati, ma non è un motivo per utilizzare sottoquery correlate. Potrebbero andare bene su Oracle, ma sono seri killer delle prestazioni su SQL Server, perché causano l'elaborazione riga per riga. Il tuo script interrogherà la tabella sys.master_files due volte per ogni riga nella tabella sys.databases.
Davos

2
Oltre al commento di Davos ... Questo script fallirà anche con errori se hai più file di dati o file di log per qualsiasi database. (ad esempio, la sottoquery ha restituito più di 1 valore.)
Arkaine55

@Davos So cosa stai dicendo ma dipende dalla frequenza con cui esegui questa query, altrimenti è una pre-ottimizzazione che probabilmente non ti serve.
adeel41

2
In genere sono d'accordo sul fatto che l'ottimizzazione iniziale sia negativa, ma quello che sto dicendo è che le sottoquery correlate sono solo un modello errato che non dovrebbe mai essere utilizzato in primo luogo. Ci sono sempre eccezioni alle regole "mai", ma questo non è uno di quei casi. So che è minore e potrebbe davvero non avere importanza qui, ma non è questo il punto. Questo è un forum pubblico che i neofiti usano per apprendere le buone pratiche, quindi è necessario fornire il codice del modello di ruolo.
Davos

1
La query genererà un errore se vengono utilizzati più file di dati in uno dei database. Ecco una versione della tua query che utilizza invece i join. Saluti! SELEZIONA db.name COME DBName, db.database_id, mfr.Physical_Name AS DataFile, mfl.Physical_Name AS LogFile DA 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' ORDINA DA db.database_id
Robert

2

Utilizzando questo script è possibile visualizzare tutti i nomi dei database e i file utilizzati (ad eccezione dei dbs di sistema).

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

1

Questo script elenca la maggior parte di ciò che stai cercando e, si spera, può essere modificato in base alle tue esigenze. Nota che sta creando una tabella permanente al suo interno: potresti volerlo cambiare. È un sottoinsieme di uno script più grande che riassume anche le informazioni sul backup e sul lavoro su vari server.

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] 

Uno script eccellente che può essere copiato / incollato e utilizzato così com'è. Una domanda però, vedo che LogVolumeFreeSpaceMBmostra sempre la stessa quantità per tutti i file, nel mio caso 44756. È possibile ottenere lo spazio libero effettivo? O è il numero di spazio libero massimo sull'unità in cui si trova l'LDF?
Abel

Ciao Abel - È passato un po 'di tempo da quando ho scritto e non sono davvero sicuro del tuo problema. Esiste un'alternativa a XP_FIXEDDRIVES chiamata sys.dm_os_volume_stats, quindi puoi provare a usarla. Se il problema è che le dimensioni dei file del database non cambiano nel tempo, ciò è normale poiché SQL Server alloca un grande blob di spazio su disco vuoto per il suo utilizzo e quindi non espande il file finché non è stato riempito. Espanderà un file a salti con la quantità determinata dalle impostazioni del file per quel particolare database
Gerard

0

La query andrà in errore se in uno dei database vengono utilizzati più file di dati (ad es. Tipi di file ".ndf").

Ecco una versione della tua query che utilizza i join invece delle sottoquery.

Saluti!

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

Lo script sottostante può essere utilizzato per ottenere le seguenti informazioni: 1. Informazioni sulla dimensione del database 2. FileSpaceInfo 3. Crescita automatica 4. Modello di recupero 5. Informazioni su 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

0

aggiungendo solo i miei 2 centesimi.

se specificatamente cercando di trovare lo spazio libero totale solo nei file di dati o solo nei file di registro in tutti i database, possiamo usare la colonna "data_space_id". 1 è per i file di dati e 0 per i file di registro.

CODICE:

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

Se si rinomina il database, MS SQL Server non rinomina i file sottostanti.

La seguente query fornisce il nome corrente del database e il nome del file logico (che potrebbe essere il nome originale del database quando è stato creato) e anche i nomi dei file fisici corrispondenti.

Nota: rimuovere il commento dall'ultima riga per visualizzare solo i file di dati effettivi

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'

Riferimento:

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

Puoi usare quanto segue:

SP_HELPDB [Master]
GO

Fornisce solo informazioni per il singolo database specificato. La domanda è per TUTTI i database.
Thronk
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.