视频1 视频21 视频41 视频61 视频文章1 视频文章21 视频文章41 视频文章61 推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37 推荐39 推荐41 推荐43 推荐45 推荐47 推荐49 关键词1 关键词101 关键词201 关键词301 关键词401 关键词501 关键词601 关键词701 关键词801 关键词901 关键词1001 关键词1101 关键词1201 关键词1301 关键词1401 关键词1501 关键词1601 关键词1701 关键词1801 关键词1901 视频扩展1 视频扩展6 视频扩展11 视频扩展16 文章1 文章201 文章401 文章601 文章801 文章1001 资讯1 资讯501 资讯1001 资讯1501 标签1 标签501 标签1001 关键词1 关键词501 关键词1001 关键词1501 专题2001
SQLSERVER将数据移到另一个文件组之后清空文件组并删除文件组
2020-11-09 07:53:15 责编:小采
文档

SQLSERVER将数据移到另一个文件组之后清空文件组并删除文件组 之前写过一篇文章: SQLSERVER将一个文件组的数据移动到另一个文件组 每个物理文件(数据文件)对应一个文件组的情况(一对一) 如果我把数据移到另一个文件组了,不想要这个已经清空的文件组了

SQLSERVER将数据移到另一个文件组之后清空文件组并删除文件组

之前写过一篇文章:SQLSERVER将一个文件组的数据移动到另一个文件组


每个物理文件(数据文件)对应一个文件组的情况(一对一)

如果我把数据移到另一个文件组了,不想要这个已经清空的文件组了,怎麽做?

脚本跟之前那篇文章差不多

 1 USE master
 2 GO
 3 
 4 
 5 IF EXISTS(SELECT * FROM sys.[databases] WHERE [database_id]=DB_ID('Test'))
 6 DROP DATABASE [Test]
 7 
 8 --1.创建数据库
 9 CREATE DATABASE [Test]
10 GO
11 
12 USE [Test]
13 GO
14 
15 
16 --2.创建文件组
17 ALTER DATABASE [Test]
18 ADD FILEGROUP [FG_Test_Id_01]
19 
20 ALTER DATABASE [Test]
21 ADD FILEGROUP [FG_Test_Id_02]
22 
23 
24 
25 --3.创建文件
26 ALTER DATABASE [Test]
27 ADD FILE
28 (NAME = N'FG_TestUnique_Id_01_data',FILENAME = N'E:\FG_TestUnique_Id_01_data.ndf',SIZE = 1MB, FILEGROWTH = 1MB )
29 TO FILEGROUP [FG_Test_Id_01];
30 
31 ALTER DATABASE [Test]
32 ADD FILE
33 (NAME = N'FG_TestUnique_Id_02_data',FILENAME = N'E:\FG_TestUnique_Id_02_data.ndf',SIZE = 1MB, FILEGROWTH = 1MB )
34 TO FILEGROUP [FG_Test_Id_02];
35 
36 
37 --4.创建表,这个表的数据存放在[FG_Test_Id_01] 文件组上
38 CREATE TABLE aa(id INT ,cname NVARCHAR(4000)) ON [FG_Test_Id_01] 
39 GO
40 
41 
42 --5.插入数据
43 INSERT INTO [dbo].[aa]
44 SELECT 1,REPLICATE('s',3000)
45 GO 500
46 
47 
48 --6.查询数据
49 SELECT * FROM [dbo].[aa]
50 
51 
52 --7.创建聚集索引在[FG_Test_Id_02]文件组上
53 CREATE CLUSTERED INDEX PK_ID ON [dbo].[aa]([id]) WITH(ONLINE=ON) ON [FG_Test_Id_02]
54 GO
55 
56 
57 --8.我们查看一下文件组的逻辑文件名
58 EXEC [sys].[sp_helpdb] @dbname = TEST -- sysname
59 
65 
66 --9.移除FG_Test_Id_01文件组
67 ALTER DATABASE TEST
68 REMOVE FILE FG_TestUnique_Id_01_data

当你移动数据到文件组[FG_Test_Id_02]上时,这时候文件组[FG_Test_Id_01]里面已经没有数据了
使用下面的脚本查看

 1 --数据库文件、大小和已经使用空间
 2 USE [Test] --要查看的当前数据库的使用空间,自动增长大小,数据库文件位置
 3 GO
 4 set nocount on
 5 create table #Data(
 6 FileID int NOT NULL,
 7 [FileGroupId] int NOT NULL,
 8 TotalExtents int NOT NULL,
 9 UsedExtents int NOT NULL,
10 [FileName] sysname NOT NULL,
11 [FilePath] nvarchar(MAX) NOT NULL,
12 [FileGroup] varchar(MAX) NULL)
13 
14 create table #Results(
15 db sysname NULL ,
16 FileType varchar(4) NOT NULL,
17 [FileGroup] sysname not null,
18 [FileName] sysname NOT NULL,
19 TotalMB numeric(18,2) NOT NULL,
20 UsedMB numeric(18,2) NOT NULL,
21 PctUsed numeric(18,2) NULL,
22 FilePath nvarchar(MAX) NULL,
23 FileID int null)
24 
25 create table #Log(
26 db sysname NOT NULL,
27 LogSize numeric(18,5) NOT NULL,
28 LogUsed numeric(18,5) NOT NULL,
29 Status int NOT NULL,
30 [FilePath] nvarchar(MAX) NULL)
31 
32 INSERT #Data (FileID, [FileGroupId], TotalExtents, UsedExtents, [FileName], [FilePath])
33 EXEC ('DBCC showfilestats WITH NO_INFOMSGS')
34 
35 update #Data
36 set #Data.FileGroup = sysfilegroups.groupname
37 from #Data, sysfilegroups
38 where #Data.FileGroupId = sysfilegroups.groupid
39 
40 INSERT INTO #Results (db, [FileGroup], FileType, [FileName], TotalMB, UsedMB, PctUsed, FilePath, FileID)
41 SELECT DB_NAME() db,
42 [FileGroup],
43 'Data' FileType,
44 [FileName],
45 TotalExtents * ./1024. TotalMB,
46 UsedExtents *./1024 UsedMB,
47 UsedExtents*100. /TotalExtents UsedPct,
48 [FilePath],
49 FileID
50 FROM #Data
51 order BY --1,2
52 DB_NAME(), [FileGroup]
53 
54 insert #Log (db,LogSize,LogUsed,Status)
55 exec('dbcc sqlperf(logspace) WITH NO_INFOMSGS ')
56 
57 insert #Results(db, [FileGroup], FileType, [FileName], TotalMB,UsedMB, PctUsed, FilePath, FileID)
58 select DB_NAME() db,
59 'Log' [FileGroup],
60 'Log' FileType,
61 s.[name] [FileName],
62 s.Size/128. as LogSize ,
63 FILEPROPERTY(s.name,'spaceused')/8.00 /16.00 As LogUsedSpace,
 ((FILEPROPERTY(s.name,'spaceused')/8.00 /16.00)*100)/(s.Size/128.) UsedPct,
65 s.FileName FilePath,
66 s.FileID FileID
67 from #Log l , master.dbo.sysaltfiles f , dbo.sysfiles s
68 where f.dbid = DB_ID()
69 and (s.status & 0x40) <> 0
70 and s.FileID = f.FileID
71 and l.db = DB_NAME()
72 
73 SELECT r.db AS "Database",
74 r.FileType AS "File type",
75 CASE
76 WHEN r.FileGroup = 'Log' Then 'N/A'
77 ELSE r.FileGroup
78 END "File group",
79 r.FileName AS "Logical file name",
80 r.TotalMB AS "Total size (MB)",
81 r.UsedMB AS "Used (MB)",
82 r.PctUsed AS "Used (%)",
83 r.FilePath AS "File name",
84 r.FileID AS "File ID",
85 CASE WHEN s.maxsize = -1 THEN null
86 ELSE CONVERT(decimal(18,2), s.maxsize /128.)
87 END "Max. size (MB)",
88 CONVERT(decimal(18,2), s.growth /128.) "Autogrowth increment (MB)"
 FROM #Results r
90 INNER JOIN dbo.sysfiles s
91 ON r.FileID = s.FileID
92 ORDER BY 1,2,3,4,5
93 
94 DROP TABLE #Data
95 DROP TABLE #Results
96 DROP TABLE #Log

View Code

使用下面的SQL语句移除文件组[FG_Test_Id_01]就可以了

 
5 --9.移除FG_Test_Id_01文件组
6 ALTER DATABASE TEST
7 REMOVE FILE FG_TestUnique_Id_01_data

此时就只剩下主文件组和[FG_Test_Id_02]文件组了

注意:如果不使用聚集索引来移动文件组[FG_Test_Id_01]上的数据到文件组[FG_Test_Id_02]

1 --4.创建表,这个表的数据存放在[FG_Test_Id_01] 文件组上
2 CREATE TABLE aa(id INT ,cname NVARCHAR(4000)) ON [FG_Test_Id_01] 
3 GO

直接使用下面SQL语句来收缩文件会报错

1 -收缩一下FG_Test_Id_01文件组文件
2 DBCC SHRINKFILE(FG_TestUnique_Id_01_data,EMPTYFILE)

报错内容

1 DBCC SHRINKFILE: 无法移动堆页 3:515。
2 消息 2555,级别 16,状态 1,第 1 行
3 无法将文件 "FG_TestUnique_Id_01_data" 的所有内容移到其他位置,以完成清空文件操作。
4 语句已终止。
5 DBCC 执行完毕。如果 DBCC 
输出了错误信息,请与系统管理员联系。 6 消息 1105,级别 17,状态 2,第 1 行 7 无法为数据库 'Test' 中的对象 'dbo.aa' 分配空间,因为 'FG_Test_Id_01' 文件组已满。请删除不需要的文件、删除文件组中的对象、将其他文件添加到文件组或为文件组中的现有文件启用自动增长,以便增加可用磁盘空间。

因为文件组[FG_Test_Id_01]里还有数据,不能清空


两个物理文件(数据文件)对应一个文件组的情况(一对多)

上面的情况是每个物理文件(数据文件)对应一个文件组的情况

下面这种情况是两个物理文件(数据文件)对于一个文件组的情况

一对一的情况使用聚集索引里移动数据,而一对一的情况使用DBCC SHRINKFILE

创建数据库

test1和test2这两个数据文件归属于主文件组primary,而数据文件test1最大大小为6MB初始大小为5MB

test2数据文件最大大小没有

使用下面脚本添加数据到主文件组

 1 --1.创建表,这个表的数据存放在主文件组上
 2 CREATE TABLE aa(id INT ,cname NVARCHAR(4000)) 
 3 GO
 4 
 5 
 6 --2.插入数据
 7 INSERT INTO [dbo].[aa]
 8 SELECT 1,REPLICATE('s',3000)
 9 GO 600
10 
11 
12 --3.查询数据
13 SELECT * FROM [dbo].[aa]
14 
15 
16 
17 
18 --4.我们查看一下文件组的逻辑文件名
19 EXEC [sys].[sp_helpdb] @dbname = TEST1
20 -- sysname
21 SELECT DB_NAME(database_id) AS DatabaseName ,
22 Name AS Logical_Name ,
23 Physical_Name ,
24 ( size * 8 ) / 1024 SizeMB
25 FROM sys.master_files
26 WHERE DB_NAME(database_id) = 'Test1'

因为第一个数据文件的最大大小,所以有一部分数据插入到了test2.ndf

现在修改test1数据文件的最大大小为20MB

相关SQL

1 ALTER DATABASE [Test1] MODIFY FILE(name='Test1',SIZE=5MB, filegrowth=1MB, MAXSIZE=20MB)

View Code

执行下面的SQL语句

1 --5.收缩文件
2 DBCC SHRINKFILE(test2,EMPTYFILE)
3 
4 
5 --6.移除test2数据文件test2.ndf
6 ALTER DATABASE TEST1
7 REMOVE FILE test2


在执行第五条语句的时候,执行下面脚本

 1 --数据库文件、大小和已经使用空间
 2 USE [Test1] --要查看的当前数据库的使用空间,自动增长大小,数据库文件位置
 3 GO
 4 set nocount on
 5 create table #Data(
 6 FileID int NOT NULL,
 7 [FileGroupId] int NOT NULL,
 8 TotalExtents int NOT NULL,
 9 UsedExtents int NOT NULL,
10 [FileName] sysname NOT NULL,
11 [FilePath] nvarchar(MAX) NOT NULL,
12 [FileGroup] varchar(MAX) NULL)
13 
14 create table #Results(
15 db sysname NULL ,
16 FileType varchar(4) NOT NULL,
17 [FileGroup] sysname not null,
18 [FileName] sysname NOT NULL,
19 TotalMB numeric(18,2) NOT NULL,
20 UsedMB numeric(18,2) NOT NULL,
21 PctUsed numeric(18,2) NULL,
22 FilePath nvarchar(MAX) NULL,
23 FileID int null)
24 
25 create table #Log(
26 db sysname NOT NULL,
27 LogSize numeric(18,5) NOT NULL,
28 LogUsed numeric(18,5) NOT NULL,
29 Status int NOT NULL,
30 [FilePath] nvarchar(MAX) NULL)
31 
32 INSERT #Data (FileID, [FileGroupId], TotalExtents, UsedExtents, [FileName], [FilePath])
33 EXEC ('DBCC showfilestats WITH NO_INFOMSGS')
34 
35 update #Data
36 set #Data.FileGroup = sysfilegroups.groupname
37 from #Data, sysfilegroups
38 where #Data.FileGroupId = sysfilegroups.groupid
39 
40 INSERT INTO #Results (db, [FileGroup], FileType, [FileName], TotalMB, UsedMB, PctUsed, FilePath, FileID)
41 SELECT DB_NAME() db,
42 [FileGroup],
43 'Data' FileType,
44 [FileName],
45 TotalExtents * ./1024. TotalMB,
46 UsedExtents *./1024 UsedMB,
47 UsedExtents*100. /TotalExtents UsedPct,
48 [FilePath],
49 FileID
50 FROM #Data
51 order BY --1,2
52 DB_NAME(), [FileGroup]
53 
54 insert #Log (db,LogSize,LogUsed,Status)
55 exec('dbcc sqlperf(logspace) WITH NO_INFOMSGS ')
56 
57 insert #Results(db, [FileGroup], FileType, [FileName], TotalMB,UsedMB, PctUsed, FilePath, FileID)
58 select DB_NAME() db,
59 'Log' [FileGroup],
60 'Log' FileType,
61 s.[name] [FileName],
62 s.Size/128. as LogSize ,
63 FILEPROPERTY(s.name,'spaceused')/8.00 /16.00 As LogUsedSpace,
 ((FILEPROPERTY(s.name,'spaceused')/8.00 /16.00)*100)/(s.Size/128.) UsedPct,
65 s.FileName FilePath,
66 s.FileID FileID
67 from #Log l , master.dbo.sysaltfiles f , dbo.sysfiles s
68 where f.dbid = DB_ID()
69 and (s.status & 0x40) <> 0
70 and s.FileID = f.FileID
71 and l.db = DB_NAME()
72 
73 SELECT r.db AS "Database",
74 r.FileType AS "File type",
75 CASE
76 WHEN r.FileGroup = 'Log' Then 'N/A'
77 ELSE r.FileGroup
78 END "File group",
79 r.FileName AS "Logical file name",
80 r.TotalMB AS "Total size (MB)",
81 r.UsedMB AS "Used (MB)",
82 r.PctUsed AS "Used (%)",
83 r.FilePath AS "File name",
84 r.FileID AS "File ID",
85 CASE WHEN s.maxsize = -1 THEN null
86 ELSE CONVERT(decimal(18,2), s.maxsize /128.)
87 END "Max. size (MB)",
88 CONVERT(decimal(18,2), s.growth /128.) "Autogrowth increment (MB)"
 FROM #Results r
90 INNER JOIN dbo.sysfiles s
91 ON r.FileID = s.FileID
92 ORDER BY 1,2,3,4,5
93 
94 DROP TABLE #Data
95 DROP TABLE #Results
96 DROP TABLE #Log

View Code

你会发现

数据都移动到了test1.mdf里去了

执行第六条SQL语句,删除test2.ndf文件

数据没有丢失

这里关键在于EMPTYFILE参数 :DBCC SHRINKFILE(test2,EMPTYFILE)


总结

这里要根据是一对多还是一对一来选择移动数据的方法

如果是一对多:使用DBCC SHRINKFILE(要移动数据的数据文件,EMPTYFILE)

如果是一对一:创建聚集索引

参考文章: [SQL]透過 DBCC SHRINKFILE([要清空的File], EMPTYFILE) 來將資料移到另一個資料檔之中

大家可以做一下实验

对于同一个文件组里的多个数据文件(不一定是主文件组),

比如有有个文件组叫[FG_Test_01],里面有两个数据文件test3.ndf和test4.ndf

test3.ndf和test4.ndf都有数据

如果我运行DBCC SHRINKFILE(test4,EMPTYFILE),test4.ndf里的数据是否会移动到test3.ndf还是会移动到test1.mdf???

这个实验留给大家o(∩_∩)o

2014-1-14补充:

这个实验的测试脚本和结果

 1 USE master
 2 GO
 3 
 4 --DROP DATABASE [Test]
 5 
 6 
 7 IF EXISTS(SELECT * FROM sys.[databases] WHERE [database_id]=DB_ID('Test'))
 8 DROP DATABASE [Test]
 9 
10 --1.创建数据库
11 CREATE DATABASE [Test]
12 GO
13 
14 USE [Test]
15 GO
16 
17 
18 --2.创建文件组
19 ALTER DATABASE [Test]
20 ADD FILEGROUP [FG_Test_Id_01]
21 
22 
23 
24 
25 
26 --3.创建文件
27 ALTER DATABASE [Test]
28 ADD FILE
29 (NAME = N'FG_TestUnique_Id_01_data',FILENAME = N'E:\FG_TestUnique_Id_01_data.ndf',SIZE = 1MB, FILEGROWTH = 1MB )
30 TO FILEGROUP [FG_Test_Id_01];
31 
32 ALTER DATABASE [Test]
33 ADD FILE
34 (NAME = N'FG_TestUnique_Id_02_data',FILENAME = N'E:\FG_TestUnique_Id_02_data.ndf',SIZE = 1MB, FILEGROWTH = 1MB )
35 TO FILEGROUP [FG_Test_Id_01];
36 
37 
38 
39 
40 
41 --4.创建表,这个表的数据存放在[FG_Test_Id_02] 文件组上
42 CREATE TABLE aa(id INT ,cname NVARCHAR(4000)) ON [FG_Test_Id_01] 
43 GO
44 
45 
46 --5.插入数据
47 INSERT INTO [dbo].[aa]
48 SELECT 1,REPLICATE('s',3000)
49 GO 1000
50 
51 
52 --6.查询数据
53 SELECT * FROM [dbo].[aa]
54 
55 
56 
57 
58 --7.我们查看一下文件组的逻辑文件名
59 EXEC [sys].[sp_helpdb] @dbname = TEST -- sysname
60 
61 
62 
63 --8.收缩文件
 DBCC SHRINKFILE(FG_TestUnique_Id_02_data,EMPTYFILE)
65 
66 
67 --9.移除FG_TestUnique_Id_03_data数据文件FG_TestUnique_Id_03_data.ndf
68 ALTER DATABASE TEST
69 REMOVE FILE FG_TestUnique_Id_02_data
70 
71 
72 
73 --10.查询数据
74 SELECT * FROM [dbo].[aa]
75 SELECT COUNT(*) FROM [dbo].[aa]

View Code

数据没有丢失

答案:

FG_TestUnique_Id_02_data.ndf里的数据会移动到FG_TestUnique_Id_01_data.ndf,不会移动到Test.mdf

因为DBCC SHRINKFILE只能在同一文件组内移动数据,而mdf只能属于主文件组primary

如有不对的地方,欢迎大家拍砖o(∩_∩)o

下载本文
显示全文
专题