轉自:https://www.cnblogs.com/woodytu/p/5821827.html
參考:https://www.sqlskills.com/blogs/paul/files-and-filegroups-survey-results/
概要
那么你應該有多少個數據文件和文件組?沒有正確的答案,而且甜蜜的地方會因你而異。
一些一般的經驗法則:
- 隨着數據庫變大,您將更需要多個文件和文件組
- 多個文件組為您提供增強的可能性,以實現有針對性的災難恢復,更輕松的可管理性和I / O子系統布局
- 每個文件組至少應有2-4個文件,tempdb是一種特殊情況
無論您做什么,不要忘記測試以找出工作負載的最佳配置。
在今天的文章里,我想談下SQL Server里非常重要的話題:SQL Server如何處理文件的文件組。當你用CREATE DATABASE命令創建一個簡單的數據庫時,SQL Server為你創建2個文件:
- 一個數據文件(.mdf)
- 一個事務日志文件(.ldf)
數據文件本身在有且只有一個主文件組里創建。默認情況下,在主文件組里,SQL Server存儲素有的數據(用戶表,系統表等)。那有額外的文件和文件組的目的是什么?我們來看下。
多個文件組
當你為你的數據創建額外的文件組,你可以在它們里面存儲你定義的表和索引,這個會在多個方面幫助你
- 你可以保持你的主文件組很小。
- 你可以把你的數據分割到多個文件組(例如,你可以在企業版里使用文件分區)。
- 你可以在文件組級別進行備份和還原操作。這給你在你的備份和還原策略上更多細粒度的控制。
- 你可以在文件組級別運行DBCC CHECKDB命令,而不是數據庫級別。
通常,你應該至少有一個從文件組,這里你可以存儲你自己創建的數據庫對象。你不應該在主文件組里存儲SQL Server為你創建的其他系統對象。
多個文件
當你創建了你自己的文件組,你也要至少放一個文件進去。另外,你可以增加額外的文件到文件組。這也會提高你的負荷性能,因為SQL Server會散步數據在所有的文件間,即所謂的輪詢調度分配算法(Round Robin Allocation Algorithm)。第一個64K在第一個文件存儲,第二個64k在第二個文件存儲,第三個區在第一個文件存儲(在你的文件組里,你有2個文件時)。
使用這個方法,SQL Server可以在緩沖池里閂鎖分配位圖頁(PFS,GAM,SGAM)的多個副本,並提高你的負荷性能。你也可以用這個方法解決在TempDb里默認配置的同個問題。另外,SQL Server也會確保文件組的所有文件在同一時間點滿——通過所謂的比例填充算法(Proportional Fill Algorithm)。因此,在文件組里你的所有文件有同樣的初始大小和自動增長參數非常重要。不然輪詢調度分配算法就不能正常工作。
實例演示
現在我們來看下一個實例,如何創建額外文件組里有多個文件在里面的數據庫。下列代碼展示了你必須用到的CREATE DATABASE命令來完成這個任務。
-- Create a new database CREATE DATABASE MultipleFileGroups ON PRIMARY ( -- Primary File Group NAME = 'MultipleFileGroups', FILENAME = 'C:\Program Files\Microsoft SQL Server\MSSQL11.SQL2012\MSSQL\DATA\MultipleFileGroups.mdf', SIZE = 5MB, MAXSIZE = UNLIMITED, FILEGROWTH = 1024KB ), -- Secondary File Group FILEGROUP FileGroup1 ( -- 1st file in the first secondary File Group NAME = 'MultipleFileGroups1', FILENAME = 'C:\Program Files\Microsoft SQL Server\MSSQL11.SQL2012\MSSQL\DATA\MultipleFileGroups1.ndf', SIZE = 1MB, MAXSIZE = UNLIMITED, FILEGROWTH = 1024KB ), ( -- 2nd file in the first secondary File Group NAME = 'MultipleFileGroups2', FILENAME = 'C:\Program Files\Microsoft SQL Server\MSSQL11.SQL2012\MSSQL\DATA\MultipleFileGroups2.ndf', SIZE = 1MB, MAXSIZE = UNLIMITED, FILEGROWTH = 1024KB ) LOG ON ( -- Log File NAME = 'MultipleFileGroups_Log', FILENAME = 'C:\Program Files\Microsoft SQL Server\MSSQL11.SQL2012\MSSQL\DATA\MultipleFileGroups.ldf', SIZE = 5MB, MAXSIZE = UNLIMITED, FILEGROWTH = 1024KB ) GO
-------------向現有數據庫添加文件組和文件
--使用sql語句添加文件組和數文件 --向E_Market數據庫進行操作 USE E_Market --添加組FG5 ALTER DATABASE E_Market ADD FILEGROUP FG5 GO --為新建的文件組添加數據文件 ALTER DATABASE E_Market ADD FILE ( name='FG5_E_Market_tada', --數據文件邏輯名稱 filename='F:\Prejoct\FG5_E_Market_tada.ndf', --存放位置--輔助數據文件 size=5MB, --文件初始大小5mb FILEGROWTH=10%, --按百分之10增長 MAXSIZE=500MB --最大考驗增到500mb ) TO FILEGROUP FG5 --將FG5設為默認文件組 ALTER DATABASE E_Market MODIFY FILEGROUP FG5 DEFAULT GO 設為默認文件組就是等於在創建文件的時候,默認文件組是為FG5
創建完數據庫后,問題是如何把表或索引放到特定的文件組?你可以用ON關鍵字人為制定文件組,如下代碼所示:
CREATE TABLE Customers ( FirstName CHAR(50) NOT NULL, LastName CHAR(50) NOT NULL, Address CHAR(100) NOT NULL, ZipCode CHAR(5) NOT NULL, Rating INT NOT NULL, ModifiedDate DATETIME NOT NULL, ) ON [FileGroup1] GO
另一個選項,你標記特定文件組為默認文件組。然后SQL Server自動創建新的數據庫對象在沒有指定ON關鍵字的文件組里。
-- FileGroup1 gets the default filegroup, where new database objects -- will be created ALTER DATABASE MultipleFileGroups MODIFY FILEGROUP FileGroup1 DEFAULT GO
這是我通常推薦的方法,因為你不需要再考慮,在創建完你的數據庫對象后。因此現在讓我們創建一個新的表,它會自動存儲在FileGroup1文件組。
-- The table will be created in the file group "FileGroup1" CREATE TABLE Test ( Filler CHAR(8000) ) GO
現在我們進行簡單的測試:我們插入40000條記錄到表。每條記錄8K大小。因此我們插入了320MB數據到表。這是我剛才提的輪詢調度分配算法,會進行操作:SQL Server會在2個文件間發放數據:第一個文件有160M的數據,第二個文件也會有160M的數據。
-- Insert 40.000 records, results in about 312MB data (40.000 x 8KB / 1024 = 312,5MB) -- They are distributed in a round-robin fashion between the files in the file group "FileGroup1" -- Each file will get about 160MB DECLARE @i INT = 1 WHILE (@i <= 40000) BEGIN INSERT INTO Test VALUES ( REPLICATE('x', 8000) ) SET @i += 1 END GO
接下來你可以在硬盤上看下,你會看到2個文件時同樣的大小。
當你把這些文件放在不同的物理硬盤上,你可以同時訪問它們。那就是在一個文件組里有多個文件的強大。
你也可以使用下列腳本獲取數據庫文件的相關信息。
--查看數據庫文件與文件組信息 SELECT name as [database_name], COUNT (*) AS [DataFiles], COUNT (DISTINCT data_space_id) AS [Filegroups], SUM (size)*8/1024 AS [Size(MB)] --default Kb FROM sys.master_files WHERE [type_desc] = N'ROWS' -- filter out log files/data_space_id 0 AND [database_id] > 0 -- filter out system databases AND [FILE_ID] != 65537 -- filter out FILESTREAM GROUP BY [database_id],name; GO
-- Retrieve file statistics information about the created database files DECLARE @dbId INT SELECT @dbId = database_id FROM sys.databases WHERE name = 'MultipleFileGroups' SELECT sys.database_files.type_desc, sys.database_files.physical_name, sys.dm_io_virtual_file_stats.* FROM sys.dm_io_virtual_file_stats ( @dbId, NULL ) INNER JOIN sys.database_files ON sys.database_files.file_id = sys.dm_io_virtual_file_stats.file_id GO