平常我不知道被问了几次这样的问题:“SQL Server里在文件组间如何移动数据?“你意识到这个问题:你只有一个主文件组的默认配置,后来围观了“SQL Server里的文件和文件组”后,你知道,有多个文件的自定义文件组会是个更好的主意。但你现在如何从主文件组里移动现有数据到新加的文件组?
这篇文章的目的是向你展示你如何在文件组间移动数据。首先我会谈下聚集和非聚集索引,然后我会谈下如何在堆表里移动数据。让我们开始吧!
移动聚集和非聚集索引
一般来说在你的表上通常应该有一个聚集索引。有了现存的聚集索引就很容易移动表数据(即聚集索引)到不同的文件组。下列代码我为表创建了一个简单的聚集和非聚集索引,并插入近800MB的测试数据到表。
CREATE TABLE TestTable ( ID INT IDENTITY(1, 1) PRIMARY KEY NOT NULL, SomeData1 INT NOT NULL, SomeData2 CHAR(5000) ) GO -- Create a supporting Non-Clustered Index CREATE NONCLUSTERED INDEX idx_SomeData1 ON TestTable(SomeData1) GO -- Insert around 800 MB of data DECLARE @i INT = 0 WHILE (@i < 100000) BEGIN INSERT INTO TestTable (SomeData1, SomeData2) VALUES (@i, REPLICATE('a', 5000)) SET @i += 1 END GO
但你在表上执行sp_help的系统存储过程,你可以看到在主文件组里看到2个索引(聚集索引和非聚集苏音)。
sp_help TestTable
假设现在我已经让你相信一个有多个文件的自定义文件组是个好主意,并且你付诸行动了:
-- Add a new file group to the database ALTER DATABASE MultipleFileGroups ADD FILEGROUP CustomFileGroup GO -- Add a new file to the previous created file group ALTER DATABASE MultipleFileGroups ADD FILE ( NAME = 'CustomFile1', FILENAME = 'C:Program FilesMicrosoft SQL ServerMSSQL11.SQL2012MSSQLDATACustomFile1.ndf', SIZE = 1048576KB, FILEGROWTH = 65536KB ) TO FILEGROUP CustomFileGroup GO -- Add a new file to the previous created file group ALTER DATABASE MultipleFileGroups ADD FILE ( NAME = 'CustomFile2', FILENAME = 'C:Program FilesMicrosoft SQL ServerMSSQL11.SQL2012MSSQLDATACustomFile2.ndf', SIZE = 1048576KB, FILEGROWTH = 65536KB ) TO FILEGROUP CustomFileGroup GO
现在的问题是现存的你的所有数据还在主文件组。你如何移动它们到新加的文件组?这个问题的答案非常简单:重建这些索引(聚集和非聚集索引)即可,并且指定新加的文件组作为目标!我们先从聚集索引开始(索引名称从sys.index里得到):
SELECT * FROM sys.indexes WHERE object_id=OBJECT_ID('TestTable')
-- Move the Clustered Index into the newly created file group CREATE UNIQUE CLUSTERED INDEX PK__TestTabl__3214EC27D9EE93A9 ON TestTable(ID) WITH ( DROP_EXISTING = ON ) ON CustomFileGroup GO
当你再次执行sp_help,你会看到SQL Server已经讲聚集索引完全移入不同的文件组。
现在我们继续处理非聚集索引:
-- Create a supporting Non-Clustered Index CREATE NONCLUSTERED INDEX idx_SomeData1 ON TestTable(SomeData1) WITH ( DROP_EXISTING = ON ) ON CustomFileGroup GO
最后,我们可以收缩主文件组的数据文件来回收已分配的空间:
-- Shrink the MDF file in the PRIMARY file group DBCC SHRINKFILE ('TestDatabase' , 0) GO
现在当你插入另一个800MB的数据,你最终可以验证新分配在新加的文件组里发生,主文件组还是很小。搞定!
移动堆表
如果你想从堆表移动数据到自定义的文件组,这需要一点技巧。主要的问题是SQL Server不提供在文件组间移动堆表数据的方法。
因此我们要变通下:你在堆表上临时创建一个聚集索引(会把数据移入自定义文件组),然后你删除聚集索引恢复为堆表。
-- Create a new Clustered Index on the Heap table that moves the data into the custom file group CREATE UNIQUE CLUSTERED INDEX idx_ci ON TestTable(ID) ON CustomFileGroup GO -- Drop the previous created Clustered Index again ;-) DROP INDEX idx_ci ON TestTable GO
我知道这样有点奇怪,但没有其他更高效的方法。另一个方法是在自定义文件组里创建新的堆表,移动数据到新的堆表,删除原来的堆表,重命名新的堆表。还不是一个完美的解决方法……
小结
在文件组间移动数据可以简单也可以复杂——取决于有没有聚集索引存在。如果你有聚集索引,你只需要在自定义文件组重建索引即可。如果你要处理堆表,你要临时增加聚集索引(它会移动表数据到别的文件组),然后删除聚集索引。真的不是个完美的解决方法……
感谢关注!
原文链接
https://www.sqlpassion.at/archive/2016/09/26/how-to-move-data-between-file-groups-in-sql-server