Menampilkan informasi tentang semua file database di SQL Server

90

Apakah mungkin untuk membuat daftar informasi tentang file (MDF / LDF) dari semua database di SQL Server?

Saya ingin mendapatkan daftar yang menunjukkan database mana yang menggunakan file apa di disk lokal.

Apa yang saya coba:

  • exec sp_databases semua database
  • select * from sys.databases menunjukkan banyak informasi tentang setiap database - tetapi sayangnya tidak menampilkan file yang digunakan oleh setiap database.
  • select * from sys.database_filesmenampilkan file mdf / ldf dari masterdatabase - tetapi bukan database lainnya
M4N
sumber

Jawaban:

123

Anda dapat menggunakan sys.master_files .

Berisi satu baris per file dari database seperti yang disimpan di database master. Ini adalah tampilan tunggal untuk seluruh sistem.

Mikael Eriksson
sumber
4
Terima kasih, itu (bergabung dengan sys.databases) adalah yang saya cari!
M4N
1
pilih * dari sys.master_files
Cosmin
2
@ M4N Jika Anda hanya ingin mendapatkan nama database, Anda juga dapat menelepon DB_NAME(database_id)sebagai gantinya bergabung dengansys.databases
Cleptus
84

Jika Anda ingin mendapatkan lokasi Database Anda dapat memeriksa Get All DBs Location .
Anda dapat menggunakan sys.master_filesuntuk mendapatkan lokasi db dan sys.databseuntuk mendapatkan nama 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
Mehdi Haghshenas
sumber
18

Saya menggunakan skrip untuk mendapatkan ruang kosong di setiap 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

Ukuran dinyatakan dalam KB.

Jānis
sumber
Apa yang Use [?]harus dilakukan? Ini memberikan kesalahan bahwa ia tidak dapat menemukan prosedur yang tersimpan itu. Menghapusnya hanya menunjukkan beberapa kali database sistem.
Abel
4

Saya telah membuat kueri ini:

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
sumber
3

Anda juga bisa mencobanya.

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

Menjalankan sql berikut (Ini hanya akan berfungsi jika Anda tidak memiliki banyak file mdf / ldf untuk database yang sama)

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

akan mengembalikan keluaran ini

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

dan database lainnya

Jika TempDB Anda memiliki beberapa MDF (seperti milik saya), skrip ini akan gagal. Namun, Anda bisa menggunakan

WHERE db.database_id > 4

pada akhirnya dan itu akan mengembalikan semua database kecuali database sistem.

adeel41
sumber
Saya menyadari ini adalah kumpulan data kecil, tetapi itu bukan alasan untuk menggunakan subkueri yang berkorelasi. Mereka mungkin baik-baik saja di Oracle tetapi mereka adalah pembunuh kinerja yang serius di SQL Server, karena mereka menyebabkan pemrosesan baris demi baris. Skrip Anda akan menanyakan tabel sys.master_files dua kali untuk setiap baris dalam tabel sys.databases.
Davos
2
Selain komentar Davos ... Skrip ini juga akan gagal dengan kesalahan jika Anda memiliki banyak file data atau file log untuk database apa pun. (misalnya Subquery mengembalikan lebih dari 1 nilai.)
Arkaine55
@Davos Saya tahu apa yang Anda katakan tetapi itu tergantung seberapa sering Anda menjalankan kueri ini jika tidak, itu adalah pra-pengoptimalan yang mungkin tidak Anda perlukan.
adeel41
2
Saya umumnya setuju bahwa pengoptimalan awal itu buruk, tetapi apa yang saya katakan adalah bahwa subkueri yang berkorelasi hanyalah pola buruk yang tidak boleh digunakan sejak awal. Selalu ada pengecualian untuk aturan 'tidak pernah', tetapi ini bukan salah satu kasus tersebut. Saya tahu ini kecil dan mungkin tidak terlalu penting di sini, tapi bukan itu intinya. Ini adalah forum publik yang digunakan pemula untuk mempelajari praktik yang baik, jadi Anda perlu memberikan kode teladan.
Davos
1
Kueri akan error jika beberapa file data digunakan di salah satu database. Berikut adalah versi kueri Anda yang menggunakan gabungan. Bersulang! PILIH db.name AS DBName, db.database_id, mfr.Physical_Name AS DataFile, mfl.Physical_Name AS LogFile DARI sys.databases db GABUNG sys.master_files mfr ON db.database_id = mfr.database_id DAN mfr.type_desc = 'ROWS' JOIN .master_files mfl ON db.database_id = mfl.database_id DAN mfl.type_desc = 'LOG' ORDER BY db.database_id
Robert
2

Dengan menggunakan skrip ini, Anda dapat menampilkan semua nama database dan file yang digunakan (dengan pengecualian dbs sistem).

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

Skrip ini mencantumkan sebagian besar dari apa yang Anda cari dan mudah-mudahan dapat dimodifikasi sesuai kebutuhan Anda. Perhatikan bahwa itu membuat tabel permanen di sana - Anda mungkin ingin mengubahnya. Ini adalah bagian dari skrip yang lebih besar yang juga merangkum informasi cadangan dan pekerjaan di berbagai 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] 
Gerard
sumber
Skrip luar biasa yang dapat disalin / ditempel dan digunakan sebagaimana adanya. Namun satu pertanyaan, saya melihat bahwa untuk LogVolumeFreeSpaceMBitu selalu menunjukkan jumlah yang sama untuk semua file, dalam kasus saya 44756. Apakah mungkin untuk mendapatkan ruang kosong yang sebenarnya? Atau apakah itu jumlah ruang kosong maksimal pada drive tempat LDF berada?
Abel
Hai Abel - Sudah lama sejak saya menulis dan saya tidak begitu yakin dengan masalah Anda. Ada alternatif untuk XP_FIXEDDRIVES yang disebut sys.dm_os_volume_stats sehingga Anda dapat mencoba menggunakannya. Jika masalahnya adalah ukuran file dari database tidak berubah dari waktu ke waktu maka itu normal karena SQL Server mengalokasikan gumpalan besar ruang disk kosong untuk penggunaannya dan kemudian tidak memperluas file itu hingga telah diisi. Ini akan memperluas file dalam lompatan dengan jumlah yang ditentukan oleh pengaturan file untuk database tertentu
Gerard
0

Query akan error jika beberapa file data (misalnya tipe file ".ndf") digunakan dalam salah satu database.

Berikut adalah versi kueri Anda menggunakan gabungan, bukan sub-kueri.

Bersulang!

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
sumber
0

Skrip di bawah ini dapat digunakan untuk mendapatkan informasi berikut: 1. Info Ukuran DB 2. FileSpaceInfo 3. Pertumbuhan Otomatis 4. Model Pemulihan 5. Informasi 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
sumber
0

hanya menambahkan 2 sen saya.

jika secara khusus mencari total ruang kosong hanya di file Data atau hanya di file Log di semua database, kita dapat menggunakan kolom "data_space_id". 1 untuk file data dan 0 untuk file log.

KODE:

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
sumber
0

Jika Anda mengganti nama Database Anda, MS SQL Server tidak mengganti nama file yang mendasarinya.

Kueri berikut memberi Anda nama saat ini dari database dan nama file logis (yang mungkin merupakan nama asli dari database saat dibuat) dan juga nama file fisik yang sesuai.

Catatan: Hapus komentar baris terakhir untuk melihat hanya file data yang sebenarnya

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'

Referensi:

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
sumber
-3

Anda dapat menggunakan di bawah ini:

SP_HELPDB [Master]
GO
Iza
sumber
Ini hanya memberikan info untuk satu database yang ditentukan. Pertanyaannya adalah untuk SEMUA database.
Thronk