1. 程式人生 > 其它 >sqlserver 分割槽表總結

sqlserver 分割槽表總結

一些結論:

1、分割槽欄位不一定需要建立索引
2、分割槽欄位可建索引:clustered 、noclustered
3、不論分割槽欄位的索引方式,若重建為clustered且沒有關聯分割槽方案時,分割槽表就變成了非分割槽表
4、普通錶轉換為分割槽表,只要在該表建立一個clustered索引,並在該clustered索引上使用分割槽方案即可
5、分割槽錶轉換為普通表,分割槽欄位新建clustered索引且不關聯分割槽方案
6、分割槽表建立唯一性約束,必須包含分割槽列
7、建立分割槽方案時,必須保證檔案組數量匹配分割槽函式的分割槽範圍段,檔案組名稱可重複,也可使用ALL(即一個檔案組),則所有分割槽均落在這  個檔案組中
8、分割槽函式和分割槽方案是面對資料庫裡的,不是整個例項的
9、分割槽表佔用磁碟大,刪除欄位後仍不會變化,進行分割槽合併或轉換為普通表,則會降低磁碟消耗

建立分割槽表步驟

建立檔案組(類似oracle表空間)->建立分割槽函式(確定資料分割槽範圍)->建立分割槽方案,關聯分割槽函式/檔案組->建立表,關聯分割槽方案

1.1、建立檔案組的示例

alter database test1 add filegroup part1;
alter database test1 add filegroup part1000;
alter database test1 add filegroup part2000;
alter database test1 add filegroup part3000;
alter database test1 add filegroup part4000;

1.2、建立檔案的示例,關聯檔案組

ALTER DATABASE test1 ADD FILE(NAME = test1part1,FILENAME = 'G:\test1part1.ndf',SIZE = 5MB,MAXSIZE = 100MB,FILEGROWTH = 5MB) TO FILEGROUP part1;
ALTER DATABASE test1 ADD FILE(NAME = test1part1000,FILENAME = 'G:\test1part1000.ndf',SIZE = 5MB,MAXSIZE = 100MB,FILEGROWTH = 5MB) TO FILEGROUP part1000;
ALTER DATABASE test1 ADD FILE(NAME = test1part2000,FILENAME = 'G:\test1part2000.ndf',SIZE = 5MB,MAXSIZE = 100MB,FILEGROWTH = 5MB) TO FILEGROUP part2000;
ALTER DATABASE test1 ADD FILE(NAME = test1part3000,FILENAME = 'G:\test1part3000.ndf',SIZE = 5MB,MAXSIZE = 100MB,FILEGROWTH = 5MB) TO FILEGROUP part3000;
ALTER DATABASE test1 ADD FILE(NAME = test1part4000,FILENAME = 'G:\test1part4000.ndf',SIZE = 5MB,MAXSIZE = 100MB,FILEGROWTH = 5MB) TO FILEGROUP part4000;

2、建立分割槽函式的示例,分割槽函式名為partfun1

-- VALUES ('1000','2000','3000','4000')表明,將把表分為5個區了,是從根據表字段的值的大小來分割槽,五個區分別是最小--1000,1000-2000,2000-3000,3000-4000,4000-最大

CREATE PARTITION FUNCTION partfun1 (int) AS RANGE LEFT FOR VALUES ('1000','2000','3000','4000')

3、建立方案的例子,關聯分割槽函式partfun1,關聯檔案組

-- 建立在part1,part1000,part2000,part3000,part4000幾個檔案組上

CREATE PARTITION SCHEME partschema1 AS PARTITION partfun1 TO (part1,part1000,part2000,part3000,part4000);

-- 建立在part1、[PRIMARY]檔案組上,把part1換成[PRIMARY]也沒問題,這樣就類似都建立在[PRIMARY]檔案組上

CREATE PARTITION SCHEME partschema2 AS PARTITION partfun1 TO (part1,[PRIMARY],[PRIMARY],[PRIMARY],[PRIMARY]);

-- 都建立在part1檔案組上

CREATE PARTITION SCHEME partschema3 AS PARTITION partfun1 ALL TO (part1);

-- 都建立在[PRIMARY]檔案組上

CREATE PARTITION SCHEME partschema4 AS PARTITION partfun1 ALL TO ([PRIMARY]);

4、建立分割槽表的示例

CREATE TABLE parttable1(
[ID] [int] NOT NULL,
[IDText] [nvarchar](max) NULL,
[Date] [datetime] NULL)
ON [partschema1](ID);

insert into parttable1 values (1,'1',getdate()-4);
insert into parttable1 values (1001,'1001',getdate()-3);
insert into parttable1 values (2001,'2001',getdate()-2);
insert into parttable1 values (3001,'3001',getdate()-1);
insert into parttable1 values (4001,'4001',getdate());

5、驗證分割槽表的資料

-- 返回分割槽表所有行

SELECT * FROM parttable1;

-- 返回ID欄位值為4的行屬於哪個分割槽

SELECT distinct $PARTITION.[partfun1](4) FROM parttable1;

-- 返回第2個分割槽的所有行,ID就是分割槽欄位ID

SELECT * FROM parttable1 where $PARTITION.[partfun1](ID)=2;

注意:不能因為SELECT * FROM parttable1 where $PARTITION.partfun1=2有結果就說明它是分割槽表,本文最後試驗7該表是非分割槽表了,但是執行SELECT * FROM parttable1 where $PARTITION.partfun1=2還是有結果的

新增分割槽

1、為分割槽方案指定一個可以使用的檔案組(新增分割槽方案的檔案組)。

2、修改分割槽函式(新增分割槽函式的資料範圍)

ALTER PARTITION SCHEME partschema1 NEXT USED [PRIMARY]

ALTER PARTITION FUNCTION partfun1() SPLIT RANGE ('4500')

select p.partition_number,p.rows from sys.indexes i inner join sys.partitions p on p.object_id = i.object_id and i.object_id = object_id('parttable2') order by 1

--第一條語句,如果分割槽方案使用的ALL TO ([PRIMARY]),則這條語句不用執行
--第二條語句新增一個分割槽,範圍是4000-4500
--第三條語句驗證新增分割槽是否存在,是否存在行數

刪除\合併分割槽

-- 就把1000-2000這個分割槽,刪除了,合併成了1000-3000

ALTER PARTITION FUNCTION partfun1() MERGE RANGE ('2000')

-- 無法像oracle一樣執行ALTER TABLE TABLENAME DROP PARTITION PARTITIONNAME;

刪除分割槽表及對應的檔案組

刪除順序為:刪除分割槽表、刪除分割槽方案、刪除分割槽函式,最後刪除檔案組,刪除完檔案組後對應的檔案也就刪除了

分割槽錶轉換為普通表,普通錶轉換為分割槽表的示例

DROP TABLE parttable1;

CREATE TABLE parttable1(
	[Id] [int] IDENTITY(1,1) NOT NULL,
	[Name] [varchar](16) NOT NULL,
	[Id2][int] NOT NULL
) ON partschema1(Id2);

insert into parttable1 values ('1',1);
insert into parttable1 values ('1001',1001);
insert into parttable1 values ('2001',2001);
insert into parttable1 values ('3001',3001);
insert into parttable1 values ('4001',4001);

1、在分割槽表上建立的唯一約束,必須包含分割槽列。

ALTER TABLE parttable1 ADD CONSTRAINT PK_prattable1_id PRIMARY KEY CLUSTERED ([ID] ASC)

報錯Column 'Id2' is partitioning column of the index 'PK_prattable1_id'. Partition columns for a unique index must be a subset of the index key.

2、分割槽列id2新建clustered索引,parttable1還是分割槽表

create clustered index CI_prattable1_id2 on parttable1(id2);

3、分割槽列id2建立nonclustered索引,parttable1還是分割槽表

drop index CI_prattable1_id2 on parttable1;
create nonclustered index NCI_prattable1_id2 on parttable1(id2);

4、非分割槽列id列建立clustered索引,parttable1還是分割槽表,說明非分割槽列可以是cluster索引列

create clustered index CI_prattable1_id on parttable1(id);

5、分割槽列id2重建為nonclustered索引並且不使用分割槽方案,parttable1還是分割槽表

create nonclustered index NCI_prattable1_id2 on parttable1(id2) WITH (DROP_EXISTING = ON) ON [PRIMARY];

6、分割槽列id2重建為clustered索引不加ON條件,parttable1還是分割槽表

drop index CI_prattable1_id on parttable1;
drop index NCI_prattable1_id2 on parttable1;
create clustered index CI_prattable1_id2 on parttable1(id2);
create clustered index CI_prattable1_id2 on parttable1(id2) WITH (DROP_EXISTING = ON);

7、分割槽列id2重建為clustered索引加上ON條件但不使用分割槽方案,parttable1變成了非分割槽表

create clustered index CI_prattable1_id2 on parttable1(id2) WITH (DROP_EXISTING = ON) ON [PRIMARY];

8、分割槽列id2重建為clustered索引並且使用分割槽方案,parttable1變成了分割槽表

create clustered index CI_prattable1_id2 on parttable1(id2) WITH (DROP_EXISTING = ON) on partschema1(Id2);

9、刪掉上面8的clustered索引後,parttable1還是分割槽表

drop index CI_prattable1_id2 on parttable1;

10、分割槽列id2新建為clustered索引並且不使用分割槽方案,parttable1變成了非分割槽表

create clustered index CI_prattable1_id2 on parttable1(id2) ON [PRIMARY];

11、刪掉上面10的clustered索引後,parttable1還是非分割槽表

drop index CI_prattable1_id2 on parttable1;

12、分割槽列id2新建為nonclustered索引,雖然使用了分割槽方案,還是非分割槽表

create nonclustered index NCI_prattable1_id2 on parttable1(id2) on partschema1(Id2);

分割槽錶轉換為普通表,遇到分割槽欄位是主鍵的情況下,則刪除主鍵約束,再對原來主鍵的欄位重建cluster索引或重建為主鍵,但是都不關聯分割槽方案

ALTER TABLE Table_name DROP CONSTRAINT PK_NAME WITH (>
CREATE CLUSTERED INDEX PK_NAME ON Table_name(column)  WITH (ON [PRIMARY];

ALTER TABLE Table_name ADD CONSTRAINT PK_NAME PRIMARY KEY CLUSTERED(column) WITH (ON [PRIMARY];

普通錶轉換為分割槽表,要保留原來的主鍵的情況下,則刪除主鍵約束,再建立主鍵但不設為聚集索引,再建立新的聚集索引,在該聚集索引中使用分割槽方案

ALTER TABLE Table_name DROP CONSTRAINT PK_NAME WITH (>
ALTER TABLE Table_name ADD CONSTRAINT PK_NAME PRIMARY KEY NONCLUSTERED(column) WITH (ON [PRIMARY];

--建立主鍵,但不設為聚集索引

CREATE CLUSTERED INDEX index_name ON Table_name(column) ON 分割槽方案(分割槽欄位)

--建立一個新的聚集索引,在該聚集索引中使用分割槽方案

查詢某張分割槽表的總行數和大小,比如表為crm.EmailLog

exec sp_spaceused 'crm.EmailLog';

查詢某張分割槽表的資訊,每個分割槽有多少行,比如表為crm.EmailLog

select convert(varchar(50), ps.name
) as partition_scheme,
p.partition_number,
convert(varchar(10), ds2.name
) as filegroup,
convert(varchar(19), isnull(v.value, ''), 120) as range_boundary,
str(p.rows, 9) as rows
from sys.indexes i
join sys.partition_schemes ps on i.data_space_id = ps.data_space_id
join sys.destination_data_spaces dds
on ps.data_space_id = dds.partition_scheme_id
join sys.data_spaces ds2 on dds.data_space_id = ds2.data_space_id
join sys.partitions p on dds.destination_id = p.partition_number
and p.object_id = i.object_id and p.index_id = i.index_id
join sys.partition_functions pf on ps.function_id = pf.function_id
LEFT JOIN sys.Partition_Range_values v on pf.function_id = v.function_id
and v.boundary_id = p.partition_number - pf.boundary_value_on_right
WHERE i.object_id = object_id('crm.EmailLog')
and i.index_id in (0, 1)
order by p.partition_number

查詢分割槽函式

select * from sys.partition_functions

檢視分割槽架構

select * from sys.partition_schemes
小小測試一枚