2013-11-21 30 views
6

有一次,我的SQL Server服务器上的数据驱动器即将用尽空间,因此必须将第二个文件添加到PRIMARY数据组,并对第一个文件的增长进行限制。这导致新数据进入第二个文件,这很好。现在我想知道哪些表在第一个文件中有数据,以便我可以知道在将数据迁移到第二个文件时哪些表将被锁定。有没有办法查看这个?查看哪些数据在SQL Server数据文件中?

回答

14

封闭是类似于您的情况的样本数据库。

-- Create database 
CREATE DATABASE [out_of_space] 
ON PRIMARY 
(NAME = N'out_of_space_dat', FILENAME = N'C:\mssql\data\out_of_space_dat.mdf' , SIZE = 4MB , FILEGROWTH = 1MB, MAXSIZE = 4MB) 
LOG ON 
(NAME = N'out_of_space_log', FILENAME = N'C:\mssql\log\out_of_space_log.ldf' , SIZE = 1MB , FILEGROWTH = 4MB , MAXSIZE = 4MB) 
GO 

-- Switch to correct database 
Use [out_of_space]; 
GO 

-- Delete existing schema. 
IF EXISTS (SELECT * FROM sys.schemas WHERE name = N'Temp') 
DROP SCHEMA [Temp] 
GO 

-- Add new schema. 
CREATE SCHEMA [Temp] AUTHORIZATION [dbo] 
GO 

-- Delete existing table 
IF OBJECT_ID(N'[Temp].[PageSplits]') > 0 
    DROP TABLE [Temp].[PageSplits] 
GO 

-- Create new table 
CREATE TABLE [Temp].[PageSplits] 
(
    [SplitId] [int] IDENTITY (1, 1) NOT NULL, 
    [SplitGuid] UNIQUEIDENTIFIER NOT NULL DEFAULT (NEWSEQUENTIALID()), 
    [SplitDt] [datetime] NOT NULL DEFAULT (getdate()), 
    CONSTRAINT [pk_Split_Guid] PRIMARY KEY CLUSTERED 
    ([SplitGuid] ASC) 
) 
GO 

-- Make 50K of records 
DECLARE @VAR_CNT INT = 1; 
WHILE (@VAR_CNT <= 50000) 
BEGIN 
    INSERT [Temp].[PageSplits] DEFAULT VALUES; 
    SET @VAR_CNT = @VAR_CNT + 1; 
END 
GO 

-- Get record count 
SELECT COUNT(*) AS TOTAL_RECS 
FROM [Temp].[PageSplits] 
GO 


-- Error Message 

/* 

Msg 1105, Level 17, State 2, Line 5 
Could not allocate space for object 'Temp.PageSplits'.'pk_Split_Guid' in database 'out_of_space' because the 'PRIMARY' filegroup is full. Create disk space by deleting unneeded files, dropping objects in the filegroup, adding additional files to the filegroup, or setting autogrowth on for existing files in the filegroup. 

*/ 

-- Show me the data file 
sp_spaceused '[Temp].[PageSplits]' 

/* 

name  rows reserved data index_size unused 
PageSplits 46870 1736 KB  1720 KB 16 KB  0 KB 

*/ 

基本上,我做了第一个主要数据文件用尽空间。

当您添加一个附加数据文件时,它会自动添加到主文件组。

-- Add another file 
ALTER DATABASE [out_of_space] 
ADD FILE 
(
    NAME = out_of_space_dat2, 
    FILENAME = N'C:\mssql\data\out_of_space_dat2.ndf', 
    SIZE = 2MB, 
    MAXSIZE = 10MB, 
    FILEGROWTH = 2MB 
); 
GO 


-- Make 5K of records 
DECLARE @VAR_CNT INT = 1; 
WHILE (@VAR_CNT <= 5000) 
BEGIN 
    INSERT [Temp].[PageSplits] DEFAULT VALUES; 
    SET @VAR_CNT = @VAR_CNT + 1; 
END 
GO 

有很多方法可以在SQL Server中查找空间使用情况。

首先是目录浏览量。阿里的解决方案不显示使用的页面,最大尺寸等。

-- Get allocation units by file and partition 
select 
    OBJECT_NAME(p.object_id) as my_table_name, 
    u.type_desc, 
    f.file_id, 
    f.name, 
    f.physical_name, 
    f.size, 
    f.max_size, 
    f.growth, 
    u.total_pages, 
    u.used_pages, 
    u.data_pages, 
    p.partition_id, 
    p.rows 
from sys.allocation_units u 
    join sys.database_files f on u.data_space_id = f.data_space_id 
    join sys.partitions p on u.container_id = p.hobt_id 
where 
    u.type in (1, 3) and 
    OBJECT_NAME(p.object_id) = 'PageSplits' 
GO 

我的解决方案确实会为您提供该信息。

enter image description here

另一种方式来获取这些信息是从动态管理视图

-- Management view (partitions) 
SELECT * FROM sys.dm_db_partition_stats 
WHERE object_id = OBJECT_ID('Temp.PageSplits'); 
GO 

enter image description here

-- Management view (files) 
SELECT db_name(database_id) as database_nm, * FROM sys.dm_db_file_space_usage 
GO 

enter image description here

重建表,以便它是在一个文件的唯一方法是创建一个新的文件组和一个新的文件。确保文件链接到新组。

-- Add a new file group 
ALTER DATABASE [out_of_space] 
ADD FILEGROUP fg_new_space 
GO 

-- Add the third data file 
ALTER DATABASE [out_of_space] 
ADD FILE 
(
    NAME = out_of_space_dat3, 
    FILENAME = N'C:\mssql\data\out_of_space_dat3.ndf', 
    SIZE = 2MB, 
    MAXSIZE = 10MB, 
    FILEGROWTH = 2MB 
) 
TO FILEGROUP fg_new_space 
GO 

删除约束并将数据移动到新的文件组。构建一个默认为表文件组的新主键。正是我们想要的。

-- Drop the constraint 
ALTER TABLE [Temp].[PageSplits] DROP CONSTRAINT [pk_Split_Guid] WITH (MOVE TO [fg_new_space]) 
GO 

-- Add back the primary key 
ALTER TABLE [Temp].[PageSplits] ADD 
CONSTRAINT [pk_Split_Guid] PRIMARY KEY CLUSTERED 
    ([SplitGuid] ASC); 

完成这篇文章的最后一项。我们可以通过SSMS获得空间计数。让我们看看表格属性。

enter image description here

让我们看一下索引属性。

enter image description here

两个表和群集索引现在对新的文件/文件组。

+0

你是说DBCC SHRINKFILE(dbdatafile1,EMPTYFILE)不会将所有的数据移动到第二个文件? – influent

+0

每个数据库都有1 * .mdf文件(主数据文件),1+ * .ndf(辅助数据文件)和1+ * .ldf日志文件。正如Microsoft所述,您不能清空.mdf文件,因为这是系统信息的数据库引导文件的位置。因此,您无法执行您正在尝试的操作。另外,由于WAL - 预写日志是单线程的,所以更多* .ldf文件对性能没有帮助。 –

+0

谢谢,但详细的答案。 – FLICKER

16

你可以使用这个脚本,看看哪些表上的文件组和他们的实际物理位置

SELECT OBJECT_NAME(i.id) AS [Table_Name] 
     , i.indid 
     , i.[name]   AS [Index_Name] 
     , i.groupid 
     , f.name    AS [File_Group] 
     , d.physical_name AS [File_Name] 
     , s.name    AS [Data_Space] 
FROM  sys.sysindexes i 
INNER JOIN sys.filegroups f  ON f.data_space_id = i.groupid 
            AND f.data_space_id = i.groupid 
INNER JOIN sys.database_files d ON f.data_space_id = d.data_space_id 
INNER JOIN sys.data_spaces s  ON f.data_space_id = s.data_space_id 
WHERE  OBJECTPROPERTY(i.id, 'IsUserTable') = 1 
ORDER BY f.name, OBJECT_NAME(i.id), groupid 
+0

令人敬畏的脚本。 +1 –

+1

其他对象的数据文件(如全文索引,非聚簇索引,SP定义等)如何修改以便它显示给定数据库中的所有对象?谢谢。 – Stackoverflowuser

+0

点对点答案!谢谢。 – FLICKER

相关问题