SQL Server 强大的分区技术(使用语句检测和优化数据库 (MSSQL个人笔记之数据库优化之路 三)

时间:2021-11-27 00:00:22

今天要一起学习下大数据处理技术:分区技术

一般在海量数据处理过程中经常会使用到分区技术把表和视图划分为不同的区域,没个区域中包含满足特定条件的数据。

 

分区的类型

 

硬分区

增加冗余的硬件设备,把数据库存储和查询任务分配到不通的硬件设备上构建高效的数据库硬件体系结构

 

分区表和分区索引

 

 

--分区技术操作详解
/********************************************************************************
*主题:SQL Server 强大的分区技术
*说明:本文是个人学习的一些笔记和个人愚见
* 有很多地方你可能觉得有异议,欢迎一起讨论

*作者:Stephenzhou(阿蒙)
*日期: 2012.07.26
*Mail:szstephenzhou@163.com
*另外:转载请著名出处。
**********************************************************************************/
use Erp_System
go

if OBJECT_ID('consume') is not null
drop table consume
go
create table consume (
id varchar(50) ,
Shopid int,
GoodsId int,
Amount float,
ConsumeDate datetime,
mark nvarchar(100)
constraint [pk_cludered_id_date] primary key clustered (id asc,ConsumeDate asc,mark)
)


declare @myid uniqueidentifier
declare @i int
set @i=0;
declare @id varchar(50);
begin
while @i<3000000
begin
set @myid=cast(newid() as nvarchar(100));
set @id='10010xxxxxxx1'
insert into consume values(@id,cast(rand()*10 as int),cast(rand()*50 as int),cast(rand()*1000 as int) ,GETDATE(),@myid);
set @i=@i+1
end;


set @i=0
while @i<3000000
begin
set @id='10010xxxxxxx2'
set @myid=cast(newid() as nvarchar(100));
insert into consume values(@id,cast(rand()*10 as int),cast(rand()*50 as int),cast(rand()*1000 as int) ,GETDATE(),@myid);
set @i=@i+1
end;

set @i=0
while @i<3000000
begin
set @id='10010xxxxxxx3'
set @myid=cast(newid() as nvarchar(100));
insert into consume values(@id,cast(rand()*10 as int),cast(rand()*50 as int),cast(rand()*1000 as int) ,GETDATE(),@myid);
set @i=@i+1
end;
end;


--select TOP 1 FROM CONSUME
--drop table consume
/*创建三个文件组*/
use Erp_System
go
alter database Erp_System add FILEGROUP FileGroup1 --创建三个文件组
alter database Erp_System add FILEGROUP FileGroup2
alter database Erp_System add FILEGROUP FileGroup3

alter database Erp_System add FILEGROUP FileGroup4
/*

有了数据后下面对文件组添加到数据文件组

*/
use Erp_System
go
alter database Erp_System add file (
name=N'10010xxxxxxx1',filename=N'D:\DATAFILE\ERP_10010xxxxxxx1.ndf',
size =5MB,maxsize =1GB,filegrowth=5MB) --size 为文件的初始大小,maxsize为文件的最大大小,filegrouwth自动增量大小
to filegroup FileGroup1



use Erp_System
go
alter database Erp_System add file (
name=N'10010xxxxxxx2',filename=N'D:\DATAFILE\ERP_10010xxxxxxx2.ndf',
size =5MB,maxsize =100MB,filegrowth=5MB) --size 为文件的初始大小,maxsize为文件的最大大小,filegrouwth自动增量大小
to filegroup FileGroup2

use Erp_System
go
alter database Erp_System add file (
name=N'10010xxxxxxx3',filename=N'D:\DATAFILE\ERP_10010xxxxxxx3.ndf',
size =5MB,maxsize =100MB,filegrowth=5MB) --size 为文件的初始大小,maxsize为文件的最大大小,filegrouwth自动增量大小
to filegroup FileGroup3



use Erp_System
go
alter database Erp_System add file (
name=N'10010xxxxxxx4',filename=N'D:\DATAFILE\ERP_10010xxxxxxx4.ndf',
size =5MB,maxsize =100MB,filegrowth=5MB) --size 为文件的初始大小,maxsize为文件的最大大小,filegrouwth自动增量大小
to filegroup FileGroup4

/*
文件组已经创建,而且已经知道放到了指定的文件中去了 .现在需要创建分区函数
以下是创建两个分区函数 需要说明的事第一个分区是按照字段id分为三个分区 其中left代表的意思是靠左边缘
而第二right表示小于等于2的为第一分区,大于2 而小于4的放到第二分区中,大于4而小于7放在第三个分区中

*/

use Erp_System
go
create partition function myid(varchar(50))--创建分区函数 其中的参数的类型为分区列的数据类型
AS range right for values('10010xxxxxxx1','10010xxxxxxx2','10010xxxxxxx3');
go

use Erp_System
go
create partition function myshopid(int)
as range right for values(2,4,7)

/*创建分区方案*/

create partition scheme myRange_id
as partition myid
to
(FileGroup1,FileGroup1,FileGroup2,FileGroup3,FileGroup3);

create partition scheme myRange_shopid
as partition myshopid
to
(FileGroup1,FileGroup1,FileGroup2,FileGroup3);
/*如上分区方案myRange_id 是把分区函数指定对应的文件组中

分区方案已经设计好了,如果使用呢??

这是很多人想的,突然发现数据那么多想使用这个技术怎么办??

其实很好办,原来的表先不动,先新建一个表使用这个方案,然后把数据导入分区表中就OK了
好了 看操作;。。
*/

use Erp_System
go

if OBJECT_ID('consumeRange') is not null
drop table consumeRange
go
create table consumeRange (
id varchar(50) ,
Shopid int,
GoodsId int,
Amount float,
ConsumeDate datetime,
mark nvarchar(100)
)on myRange_id(id)



/*
如上已经创建分区表指定了分区方案myRange_id,接下来就拷贝数据就好了
看下面。。。 把原来海量的数据表consume导入到consumeRange
导入有点慢 。。。。。等。。
*/

insert into consumeRange select * from consume
/*
出现错误
消息 1105,级别 17,状态 2,第 1 行
无法为数据库 'Erp_System' 中的对象 'dbo.consumeRange' 分配空间,因为 'FileGroup1' 文件组已满。请删除不需要的文件、删除文件组中的对象、将其他文件添加到文件组或为文件组中的现有文件启用自动增长,以便增加可用磁盘空间。

很明显文件组的maxsize100mb是不够的了 查看文件已经100 MB (104,857,600 字节 改大点。。
*/

ALTER DATABASE Erp_System MODIFY FILE (NAME=N'10010xxxxxxx1', maxsize=1GB)
ALTER DATABASE Erp_System MODIFY FILE (NAME=N'10010xxxxxxx2', maxsize=1GB)
ALTER DATABASE Erp_System MODIFY FILE (NAME=N'10010xxxxxxx3', maxsize=1GB)

--继续导入不过要删除之前已经导入的 不然又有重复的.

truncate table consumeRange

insert into consumeRange select * from consume

/*
导入完了 数据也不多
(9000000 行受影响)
数据导入好了,看下下面两个语句的执行计划就可以很明显的看到分区表的好处了。。。

*/
select id from consume where id='10010xxxxxxx1' or id='10010xxxxxxx3'
-- 用了00:01:36
select id from consumeRange where id='10010xxxxxxx1' or id='10010xxxxxxx3'
-- 用了00:01:25

--创建 分区索引 值是在后面加了 on 分区方案(参数)

create NONCLUSTERED index in_idex on consumeRange(id)
on myRange_id(id)

select * from consumeRange where id='10010xxxxxxx1'
-- 用了00:01:21
--当年这是我的机器跑出来的 估计每个人的机器不一样。。
select $PARTITION.myid('10010xxxxxxx3')
/*

-----------
3

(1 行受影响)

*/

select $partition.myid(id) as partitionnumber,COUNT(1) recordcount from consumeRange
group by $partition.myid(id)
/*
partitionnumber recordcount
--------------- -----------
1 3001000
2 3000000
3 3000000

(3 行受影响)

*/


--查询第二个分区的数据如下
select * from consumeRange where $partition.myid(id)=2


 

 

今天到此为止,明天继续更新。。