如何將數據與特定分區對齊?加上與同一個表分區相關的其他2個問題
我正在創建一個用於測試目的的表:
begin try drop table countries end try begin catch end catch go create table countries( name nvarchar(100) not null, visit date not null, constraint pk__countries primary key clustered (visit,name)) set nocount on insert into countries VALUES ('Portugal-Lisbon','20111101') insert into countries VALUES ('Spain-Madrid','20111101') insert into countries VALUES ('Italia-Milano','20120101') insert into countries VALUES ('Norway-Thromso','20121201') insert into countries VALUES ('USA-California','20160110') insert into countries VALUES ('Brasil-Porto Alegre','20131101') insert into countries VALUES ('Lithuania-Vilnius','20131101') insert into countries VALUES ('France-Paris','20131101') insert into countries VALUES ('Russia-Moscow','20141101') insert into countries VALUES ('Germany-Liepzig','20140901') insert into countries VALUES ('Germany-Hamburg','20100901') insert into countries VALUES ('Estonia-Viru','20151101') insert into countries VALUES ('Sweden-Gotemborg','20151101') insert into countries VALUES ('Latvia-Riga','20141101') insert into countries VALUES ('India-Vrindavana','20151101') insert into countries VALUES ('Switzerland-Lugano','20161101') insert into countries VALUES ('USA-New York','20160110') insert into countries VALUES ('Russia-Cheliabinsky','20170110') insert into countries VALUES ('Italia-Bergamo','20170101') insert into countries VALUES ('UK-Telford','20170405') insert into countries VALUES ('Spain-Barcelona','20101101') insert into countries VALUES ('Spain-Fuerteventura','20101001')
然後我創建我的分區函式和分區模式:
--------------------------------------------------------------------------------------- --- create a partition function -- https://technet.microsoft.com/en-us/library/ms186307(v=sql.110).aspx --------------------------------------------------------------------------------------- use radhe go IF EXISTS (SELECT * FROM sys.partition_functions WHERE name = 'PF_year') DROP PARTITION FUNCTION PF_year ; GO CREATE PARTITION FUNCTION PF_year (date) AS RANGE RIGHT FOR VALUES ( '20100101', '20110101', '20120101', '20130101', '20140101', '20150101', '20160101'); --------------------------------------------------------------------------------------- --- Create a Partition Scheme --------------------------------------------------------------------------------------- use radhe go DROP PARTITION SCHEME PSC_YEAR GO CREATE PARTITION SCHEME PSC_YEAR AS PARTITION PF_year TO ([PRIMARY],[F0],[F1], [F2], [F3], [F4], [F5], [F6]) GO
之後,我讓我的表使用分區模式:
--================================================================================ --================================================================================ use radhe go ALTER TABLE countries DROP CONSTRAINT [pk__countries] go CREATE UNIQUE CLUSTERED INDEX pk__countries ON dbo.countries (visit desc ,name asc) WITH (DROP_EXISTING=off,ONLINE=Off,FILLFACTOR=100,DATA_COMPRESSION=PAGE) ON PSC_YEAR (visit) go
所有這些都完成了 - 為了驗證一切都完成了,我有以下腳本來檢查每個分區中有多少行:
SELECT [table_name] = SCHEMA_NAME([schema_id]) + '.' + t.[name] ,i.[name] AS [index_name] ,i.[type_desc] AS [index_type] ,ps.[name] AS [partition_scheme] ,pf.[name] AS [partition_function] ,p.[partition_number] ,r.[value] AS [current_partition_range_boundary_value] ,p.[rows] AS [partition_rows] ,p.[data_compression_desc] FROM sys.tables t INNER JOIN sys.partitions p ON p.[object_id] = t.[object_id] INNER JOIN sys.indexes i ON p.[object_id] = i.[object_id] AND p.[index_id] = i.[index_id] INNER JOIN sys.data_spaces ds ON i.[data_space_id] = ds.[data_space_id] INNER JOIN sys.partition_schemes ps ON ds.[data_space_id] = ps.[data_space_id] INNER JOIN sys.partition_functions pf ON ps.[function_id] = pf.[function_id] LEFT JOIN sys.partition_range_values AS r ON pf.[function_id] = r.[function_id] AND r.[boundary_id] = p.[partition_number] where t.object_id = object_id('dbo.countries') GROUP BY SCHEMA_NAME([schema_id]) ,t.[name] ,i.[name] ,i.[type_desc] ,ps.[name] ,pf.[name] ,p.[partition_number] ,r.[value] ,p.[rows] ,p.[data_compression_desc] ORDER BY SCHEMA_NAME([schema_id]) ,t.[name] ,i.[name] ,p.[partition_number];
但是當我執行以下腳本時,要查看我每年有多少行(因為我每年進行分區),我得到以下結果:
select c.name, [year of visit] = year(visit), [number of visits] = count(*) over (partition by year(visit)) from countries c order by visit desc
為什麼我 2010 年的記錄不在分區 1 上?
我可以準確找出記錄在哪個分區上嗎?
如何添加另一個分區,假設明年(2018 年)我將添加 2017 年的分區,而無需重建聚集索引?
最後但同樣重要的是,假設幾年後,我將不再對 2010 年的行感興趣。我怎樣才能擺脫所有的分區?
下面是這個數據庫的創建方式,基本上我的目標是將每個分區放在不同的文件上。
CREATE DATABASE [radhe] CONTAINMENT = NONE ON PRIMARY ( NAME = N'radhe', FILENAME = N'C:\Program Files\Microsoft SQL Server\MSSQL12.SQL2014\MSSQL\DATA\radhe.mdf' , SIZE = 70254592KB , MAXSIZE = UNLIMITED, FILEGROWTH = 1048576KB ), FILEGROUP [F0] ( NAME = N'F0', FILENAME = N'C:\sql2014_data\RADHE0.ndf' , SIZE = 1048576KB , MAXSIZE = UNLIMITED, FILEGROWTH = 1048576KB ), FILEGROUP [F1] ( NAME = N'F1', FILENAME = N'C:\sql2014_data\RADHE1.ndf' , SIZE = 1048576KB , MAXSIZE = UNLIMITED, FILEGROWTH = 1048576KB ), FILEGROUP [F2] ( NAME = N'F2', FILENAME = N'C:\sql2014_data\RADHE2.ndf' , SIZE = 3145728KB , MAXSIZE = UNLIMITED, FILEGROWTH = 1048576KB ), FILEGROUP [F3] ( NAME = N'F3', FILENAME = N'C:\sql2014_data\RADHE3.ndf' , SIZE = 3145728KB , MAXSIZE = UNLIMITED, FILEGROWTH = 1048576KB ), FILEGROUP [F4] ( NAME = N'F4', FILENAME = N'C:\sql2014_data\RADHE4.ndf' , SIZE = 3145728KB , MAXSIZE = UNLIMITED, FILEGROWTH = 1048576KB ), FILEGROUP [F5] ( NAME = N'F5', FILENAME = N'C:\sql2014_data\RADHE5.ndf' , SIZE = 3145728KB , MAXSIZE = UNLIMITED, FILEGROWTH = 1048576KB ), FILEGROUP [F6] ( NAME = N'F6', FILENAME = N'C:\sql2014_data\RADHE6.ndf' , SIZE = 3145728KB , MAXSIZE = UNLIMITED, FILEGROWTH = 1048576KB ), FILEGROUP [F7] ( NAME = N'F7', FILENAME = N'C:\sql2014_data\RADHE7.ndf' , SIZE = 1048576KB , MAXSIZE = UNLIMITED, FILEGROWTH = 1048576KB ), FILEGROUP [Facts ] ( NAME = N'Facts', FILENAME = N'C:\sql2014_data\facts.ndf' , SIZE = 45613056KB , MAXSIZE = UNLIMITED, FILEGROWTH = 1048576KB ), FILEGROUP [Facts2] ( NAME = N'Facts2', FILENAME = N'C:\sql2014_data\facts2.ndf' , SIZE = 59244544KB , MAXSIZE = UNLIMITED, FILEGROWTH = 1048576KB ) LOG ON ( NAME = N'radhe_log', FILENAME = N'C:\Program Files\Microsoft SQL Server\MSSQL12.SQL2014\MSSQL\DATA\radhe_log.ldf' , SIZE = 2097152KB , MAXSIZE = 2048GB , FILEGROWTH = 1048576KB ) END
下面的這些連結是有關表分區的有趣參考:
為什麼我 2010 年的記錄不在分區 1 上?
使用
RANGE RIGHT
函式,大於或等於第一個邊界 (‘20100101’) 且小於第二個邊界 (‘20110101’) 的值儲存在分區 2 中。只有小於第一個 ‘20100101’ 邊界的行儲存在分區 1 中。您的測試數據中沒有任何行符合此條件。我可以準確找出記錄在哪個分區上嗎?
$PARTITION
使用與分區列值一起呼叫分區函式:SELECT visit , $PARTITION.PF_Year(visit) AS PartitionNumber FROM dbo.countries;
如何添加另一個分區,假設明年(2018 年)我將添加 2017 年的分區,而無需重建聚集索引?
將分區方案
NEXT USED
文件組設置為所需的文件組和SPLIT
具有新邊界的函式。這應該在 2018 年數據存在之前完成,理想情況下,現有分區 (2017) 為空,以避免代價高昂的數據移動。ALTER PARTITION SCHEME PSC_YEAR NEXT USED [F8]; ALTER PARTITION FUNCTION PF_Year() SPLIT RANGE('20180101');
最後但同樣重要的是,假設幾年後,我將不再對 2010 年的行感興趣。我怎樣才能擺脫所有的分區?
SWITCH
將分區放入相同模式的對齊臨時表中,並使用 . 刪除分區邊界MERGE
。我建議使用與源相同的方案對臨時表進行分區,以確保對齊並在SWITCH
.CREATE TABLE dbo.countries_staging( name nvarchar(100) not null , visit date not null ); CREATE UNIQUE CLUSTERED INDEX pk__countries_staging ON dbo.countries_staging (visit desc ,name asc) WITH(DATA_COMPRESSION=PAGE) ON PSC_YEAR (visit); GO ALTER TABLE dbo.countries SWITCH PARTITION $PARTITION.PF_Year('20100101') TO dbo.countries_staging PARTITION $PARTITION.PF_Year('20100101'); TRUNCATE TABLE dbo.countries_staging; ALTER PARTITION FUNCTION PF_Year() MERGE RANGE('20100101'); GO