Listado de información sobre todos los archivos de base de datos en SQL Server

90

¿Es posible enumerar información sobre los archivos (MDF / LDF) de todas las bases de datos en un servidor SQL?

Me gustaría obtener una lista que muestre qué base de datos está usando qué archivos en el disco local.

Lo que probé:

  • exec sp_databases todas las bases de datos
  • select * from sys.databases muestra mucha información sobre cada base de datos, pero desafortunadamente no muestra los archivos utilizados por cada base de datos.
  • select * from sys.database_filesmuestra los archivos mdf / ldf de la masterbase de datos, pero no las otras bases de datos
M4N
fuente

Respuestas:

123

Puede utilizar sys.master_files .

Contiene una fila por archivo de una base de datos almacenada en la base de datos maestra. Esta es una vista única de todo el sistema.

Mikael Eriksson
fuente
4
Gracias, eso (unido a sys.databases) es lo que estaba buscando.
M4N
1
seleccione * de sys.master_files
Cosmin
2
@ M4N Si solo desea obtener el nombre de la base de datos, también puede llamar en DB_NAME(database_id)lugar de unirse asys.databases
Cleptus
84

Si desea obtener la ubicación de la base de datos, puede marcar Obtener la ubicación de todas las bases de datos .
puede usar sys.master_filespara obtener la ubicación de la base de datos y sys.databseobtener el nombre de la base de datos

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
Mehdi Haghshenas
fuente
18

Estoy usando un script para obtener un espacio vacío en cada archivo:

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

El tamaño se expresa en KB.

Jānis
fuente
¿Qué se Use [?]supone que debo hacer? Da un error que no puede encontrar ese procedimiento almacenado. Al eliminarlo, solo se muestran varias veces las bases de datos del sistema.
Abel
4

He creado esta consulta:

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
Alexandru-Codrin Panaite
fuente
3

También puedes probar esto.

 select db_name(dbid) dbname, filename from sys.sysaltfiles
Joe Pi
fuente
3

Ejecutando el siguiente sql (solo funcionará cuando no tenga varios archivos mdf / ldf para la misma base de datos)

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

devolverá esta salida

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

y resto de bases de datos

Si sus TempDB tienen múltiples MDF (como el mío), este script fallará. Sin embargo, puede utilizar

WHERE db.database_id > 4

al final y devolverá todas las bases de datos excepto las del sistema.

adeel41
fuente
Me doy cuenta de que es un conjunto de datos pequeño, pero eso no es motivo para usar subconsultas correlacionadas. Pueden estar bien en Oracle, pero son serios asesinos del rendimiento en SQL Server, porque causan procesamiento fila por fila. Su secuencia de comandos consultará la tabla sys.master_files dos veces por cada fila en la tabla sys.databases.
Davos
2
Además del comentario de Davos ... Este script también fallará con errores si tiene varios archivos de datos o archivos de registro para cualquier base de datos. (por ejemplo, la subconsulta devolvió más de 1 valor).
Arkaine55
@Davos Sé lo que está diciendo, pero depende de la frecuencia con la que ejecute esta consulta; de lo contrario, es una optimización previa que probablemente no necesite.
adeel41
2
En general, estoy de acuerdo en que la optimización temprana es mala, pero lo que estoy diciendo es que las subconsultas correlacionadas son solo un patrón incorrecto que nunca debería usarse en primer lugar. Siempre hay excepciones a las reglas de "nunca", pero este no es uno de esos casos. Sé que es menor y puede que no importe aquí, pero ese no es el punto. Este es un foro público que los novatos utilizan para aprender buenas prácticas, por lo que debe proporcionar un código de modelo a seguir.
Davos
1
La consulta generará un error si se utilizan varios archivos de datos en una de las bases de datos. Aquí hay una versión de su consulta que usa combinaciones en su lugar. ¡Salud! SELECCIONE db.name COMO 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 Y mfr.typeS 'JOIN =' RysOW .master_files mfl ON db.database_id = mfl.database_id AND mfl.type_desc = 'LOG' ORDER BY db.database_id
Robert
2

Con este script, puede mostrar todos los nombres de las bases de datos y los archivos utilizados (con excepción de la base de datos del sistema).

select name,physical_name from sys.master_files where database_id > 4
Jorge Cribb
fuente
1

Este script enumera la mayor parte de lo que está buscando y, con suerte, puede modificarse según sus necesidades. Tenga en cuenta que está creando una tabla permanente allí; es posible que desee cambiarla. Es un subconjunto de un script más grande que también resume la información de respaldo y trabajo en varios servidores.

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] 
Gerard
fuente
Un excelente script que se puede copiar / pegar y usar tal cual. Sin embargo, una pregunta, veo que LogVolumeFreeSpaceMBsiempre muestra la misma cantidad para todos los archivos, en mi caso 44756. ¿Es posible obtener el espacio libre real? ¿O es la cantidad máxima de espacio libre en la unidad donde se encuentra el LDF?
Abel
Hola Abel - Ha pasado un tiempo desde que escribí y no estoy muy seguro de tu problema. Existe una alternativa a XP_FIXEDDRIVES llamada sys.dm_os_volume_stats, por lo que puede intentar usarla. Si el problema es que los tamaños de archivo de la base de datos no cambian con el tiempo, entonces eso es normal ya que SQL Server asigna una gran cantidad de espacio en disco vacío para su uso y luego no expande ese archivo hasta que se haya llenado. Expandirá un archivo en saltos con la cantidad determinada por la configuración del archivo para esa base de datos en particular
Gerard
0

La consulta generará un error si se utilizan varios archivos de datos (por ejemplo, tipos de archivo ".ndf") en una de las bases de datos.

Aquí hay una versión de su consulta que utiliza combinaciones en lugar de subconsultas.

¡Salud!

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
Robert
fuente
0

El siguiente script se puede utilizar para obtener la siguiente información: 1. Información del tamaño de la base de datos 2. FileSpaceInfo 3. AutoGrowth 4. Modelo de recuperación 5. Información de 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
Vinod Narwal
fuente
0

simplemente agregando mis 2 centavos.

si buscamos específicamente encontrar espacio libre total solo en archivos de datos o solo en archivos de registro en todas las bases de datos, podemos usar la columna "data_space_id". 1 es para archivos de datos y 0 para archivos de registro.

CÓDIGO:

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 

Raj Nair
fuente
0

Si cambia el nombre de su base de datos, MS SQL Server no cambia el nombre de los archivos subyacentes.

La siguiente consulta le proporciona el nombre actual de la base de datos y el nombre del archivo lógico (que podría ser el nombre original de la base de datos cuando se creó) y también los nombres de los archivos físicos correspondientes.

Nota: Elimine los comentarios de la última línea para ver solo los archivos de datos reales

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'

Referencia:

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

ssh
fuente
-3

Puede utilizar lo siguiente:

SP_HELPDB [Master]
GO
Iza
fuente
Esto solo proporciona información para la única base de datos especificada. La pregunta es para TODAS las bases de datos.
Thronk