8、SQL Server 表分区

什么是表分区?
表分区其实就是将一个大表分成若干个小表,可以将一些不需要经常操作的数据存在其他的表,然后想查询哪个表的记录,就去对应的表中查询,由于表中的记录变少了,查询的时间也就少了。
表分区可以从物理上将一个大表分成几个小表,但是逻辑上还是一个表。所以当执行插入操作的时候,不需要我们去判断应该插入到哪个表中。只需要插入大表中就可以了。SQL Server会自动的将它放在对应的表中。对于查询也是一样,直接查询大表就可以了。

什么时候需要表分区?
当数据量过百万时,访问速度明显变慢,并且你的数据是按某一规则进行区分的数据时可以考虑表分区。(相当于一本厚书,按需要分为几个小本,这样书就变薄了,找资料也就更精确了)

创建分区表

一、创建文件组

其实可以使用默认的primary组,但是为了更方便管理以及提高运行速度,所以还是应该创建几个分组。

1、使用SSMS创建文件组

2、使用T-SQL创建文件组

--alter database <数据库名> add filegroup <文件组名>
alter database webDB add filegroup group2013
alter database webDB add filegroup group2014
alter database webDB add filegroup group2015

二、为文件组添加数据库文件

1、使用SSMS添加数据库文件

2、使用T-SQL添加数据库文件

--alter database <数据库名称> add file <数据标识> to filegroup <文件组名称>
alter database webDB add file
(
    name=‘web2013‘,
    filename=‘D:\web2013.ndf‘,
    size=5mb,
    filegrowth=5mb
)
to filegroup group2013
alter database webDB add file
(
    name=‘web2014‘,
    filename=‘D:\web2014.ndf‘,
    size=5mb,
    filegrowth=5mb
)
to filegroup group2014

alter database webDB add file
(
    name=‘web2015‘,
    filename=‘D:\web2015.ndf‘,
    size=5mb,
    filegrowth=5mb
)
to filegroup group2015

注意:尽可能的将不同的文件放在不同的硬盘分区里,或者独立硬盘中。这样可以加快SQL Server运行速度。

三、创建分区函数

分区函数用来告诉SQL Server用什么样的规则进行分区,这一步必须使用T-SQL脚本来执行了。

create partition function fenqu(datetime) --分区函数名
as range right  --right分区方式 边界值去左表还是右表
for values (‘2014-01-01‘,‘2015-01-01‘) --按这些值来分区
--group2013 : 2014-01-01 之前的
--group2014 : 2014-01-01 到 2014-12-31的
--group2015 : 2015-01-01 之后的

四、创建分区方案

create partition scheme SchemeFenqu --分区方案名
as partition fenqu    --之前创建的分区函数
to(group2013,group2014,group2015) --跟放的文件组

创建完分区函数和分区方案后可以在存储中查看

五、创建分区表

create table fenquTable
(
    id int identity(1,1) not null,
    name varchar(20) not null,
    createTime datetime not null
) on SchemeFenqu(createTime) --调用分区方案

注意:不可以使用聚集索引,因为聚集索引是存在连续的物理地址中的,而表分区是将数据分别存储在不同表中的。

至此物理上分离的,逻辑上一体的分区表就创建完了。

操作分区表

一、插入数据

--插入测试数据
insert into fenquTable(name,createTime) values (‘隔壁老王‘,‘2010-01-01‘)
insert into fenquTable(name,createTime) values (‘隔壁老张‘,‘2011-01-01‘)
insert into fenquTable(name,createTime) values (‘隔壁老赵‘,‘2012-01-01‘)
insert into fenquTable(name,createTime) values (‘隔壁老李‘,‘2013-01-01‘)
insert into fenquTable(name,createTime) values (‘老李儿子‘,‘2013-10-01‘)
insert into fenquTable(name,createTime) values (‘隔壁老田‘,‘2014-01-01‘)
insert into fenquTable(name,createTime) values (‘隔壁老梁‘,‘2015-01-01‘)
insert into fenquTable(name,createTime) values (‘老梁姑娘楠楠‘,‘2015-10-10‘)

跟插入普通表没有任何区别,不用管他放在哪个物理磁盘上。

二、查询数据

--查询数据
select * from fenquTable

查询也是如此,不用考虑哪个磁盘,逻辑上都属于同一个表,基本上看不出区别。如果需要查看哪条插入到哪个物理的分区表中,可以使用$partition函数查看。

--语法:$partition.分区函数名(表达式)
--查看该表达式下有多少数据
select $partition.fenqu(‘2015-01-01‘) --返回3

--查看分区表明细
select * from fenquTable where $partition.fenqu(createTime)=1
select * from fenquTable where $partition.fenqu(createTime)=2
select * from fenquTable where $partition.fenqu(createTime)=3

--查看分区表中的记录数
select $partition.fenqu(createTime) as 分区 ,count(id) from fenquTable
group by $partition.fenqu(createTime)

三、修改数据

select $partition.fenqu(createTime) as 分区,count(id) as 数量 from fenquTable
group by $partition.fenqu(createTime)
--分区    数量
--1            5
--2            1
--3            2

update fenquTable set createTime =‘2015-01-01‘ where id = 1

select $partition.fenqu(createTime) as 分区,count(id) as 数量 from fenquTable
group by $partition.fenqu(createTime)
--分区    数量
--1            4
--2            1
--3            3

可以明显看到,跟普通修改没有区别,SQL Server可以自动帮我们重新划分分区,将数据从第一个分区移动到第五个分区中。

普通表转分区表

上面介绍了如何在创建表的时候进行分区,但往往我们需要的是将现有的普通表在数据保留的情况下进行分区。

普通表一般都有主键,同时还是聚集索引。分区是以某个字段为条件进行的,而除了这个字段其他字段是不可以创建聚集索引的。所以需要先删除表中的聚集索引,再新建一个聚集索引。

--删除主键,自动同时删除索引
alter table newTable drop constraint PK_newTable 

--创建主键,但不创建聚集索引
alter table newTable add constraint PK_newTable
primary key nonclustered --非聚集
(
    id asc
) on [primary]

--然后给我们亲爱的时间创建一个聚集索引
create clustered index CT_newTable on newTable(createTime)
on schemeFenqu(createTime) --并调用分区方案

--然后再查询分区,发现数据保留情况下,已经将数据按规则进行分区了
select $partition.fenqu(createTime) as 分区,count(id) as 数量
from newTable group by $partition.fenqu(createTime)

添加分区

向上面只分了3个区,而15年以后的都存在第三个分区中,到16年还是会存在这个分区中,这时候需要再新加一个16年的分区。

添加新的分区意味着要新建一个文件组和文件来存放这个分区表,然后在分区方案中用到这个文件组,最后再修改一下分区函数的规则即可。文件组和分区数量要保持一致。

--创建文件组
alter database webDB add filegroup group2016

--添加数据库文件
alter database webDB add file
(
    name=‘web2016‘,
    filename=‘D:\web2016.ndf‘,
    size=5mb,
    filegrowth=5mb
)
to filegroup group2016

--修改分区方案
alter partition scheme SchemeFenqu
next used group2016

--修改分区函数
alter partition function fenqu()
split range(‘2016-01-01‘)

--添加2016年数据
insert into newTable (name,createTime) values (‘16年小明‘,‘2016-03-05‘)

--查看分区及统计
select $partition.fenqu(createTime) as 分区,count(id) as 数量
from newTable group by $partition.fenqu(createTime)

删除分区

删除分区就是将分区函数中多余的边界值删除。

如:2013,2014,2015,2016 现在需要将13年和14年进行合并,删除13年的分区。

--查看分区及统计
select $partition.fenqu(createTime) as 分区,count(id) as 数量
from newTable group by $partition.fenqu(createTime)
--分区    数量
--1        4
--2        1
--3        3
--4        1

--删掉该边界值
alter partition function fenqu() merge range(‘2014-01-01‘)

--再次查询
select $partition.fenqu(createTime) as 分区,count(id) as 数量
from newTable group by $partition.fenqu(createTime)
--分区    数量
--1        5
--2        3
--3        1

拆分分区

有的时候某一分区中数据量过大,需要将这个分区再次拆分为多个分区,以加快访问速度。

拆分分区的操作其实与添加分区类似,首先要添加文件组、文件、修改分区方案、修改分区函数(新增一个边界值)。

如:2014,2015,2015年6月份以上一个 6月份一下一个。

--查看分区及统计
select $partition.fenqu(createTime) as 分区,count(id) as 数量
from newTable group by $partition.fenqu(createTime)
--分区        数量
--1            5
--2            3
--3            1

--创建文件组
alter database webDB add filegroup group2014_2015

--添加数据库文件
alter database webDB add file
(
    name=‘web2014_2015‘,
    filename=‘D:\web2014_2015.ndf‘,
    size=5mb,
    filegrowth=5mb
)
to filegroup group2014_2015

--修改分区方案
alter partition scheme SchemeFenqu
next used group2014_2015

--修改分区函数
alter partition function fenqu()
split range(‘2015-06-01‘)

--查看分区及统计
select $partition.fenqu(createTime) as 分区,count(id) as 数量
from newTable group by $partition.fenqu(createTime)
--分区        数量
--1            5
--2            2
--3            1
--4            1

分区表转普通表

--修改分区函数 将边界值都删除
alter partition function fenqu()
merge range(‘2013-01-01‘)
alter partition function fenqu()
merge range(‘2014-01-01‘)
alter partition function fenqu()
merge range(‘2015-01-01‘)
alter partition function fenqu()
merge range(‘2015-06-01‘)

select $partition.fenqu(createTime) as 分区,count(id) as 数量
from newTable group by $partition.fenqu(createTime)
--这时只有一个分区了
--分区    数量
--1        9

这样虽然只有一个分区了,但是查看数据表存储位置,是否进行分区:True,分区数1.

--重新建立聚集索引
create clustered index CT_newTable on newTable(createTime)
    with(drop_existing=on) --如果存在则删除
on [primary]

删除分区索引后,重新建立聚集索引,这时再此查看数据表的存储位置,是否分区:Flase。

时间: 2024-10-15 07:56:14

8、SQL Server 表分区的相关文章

SQL Server表分区详解

原文:SQL Server表分区详解 什么是表分区 一般情况下,我们建立数据库表时,表数据都存放在一个文件里. 但是如果是分区表的话,表数据就会按照你指定的规则分放到不同的文件里,把一个大的数据文件拆分为多个小文件,还可以把这些小文件放在不同的磁盘下由多个cpu进行处理.这样文件的大小随着拆分而减小,还得到硬件系统的加强,自然对我们操作数据是大大有利的. 所以大数据量的数据表,对分区的需要还是必要的,因为它可以提高select效率,还可以对历史数据经行区分存档等.但是数据量少的数据就不要凑这个热

SQL SERVER 表分区

一 .SQL SERVER 表分区介绍: SQL Server  引入的表分区技术,让用户能够把数据分散存放到不同的物理磁盘中,提高这些磁盘的并行处理性能以优化查询性能…… 二 .SQL SERVER 数据库表分区由三个步骤来完成: 1.创建分区函数 2.创建分区架构 3.对表进行分区 基于缓存更新机制,我使用时间来进行分区,这里大家根据业务的要求使用合适的字段来作为分区 创建数据库分区文件数量,这里存储一年的数据分成十二个分区,需要现在D盘建立好Data 的文件夹 里面包含Primary 文件

SQL Server表分区的NULL值问题

SQL Server表分区的NULL值问题 SQL Server表分区只支持range分区这一种类型,往往会被大家吐槽 人家MySQL支持四种类型:RANGE分区.LIST分区.HASH分区.KEY分区 共同点是MySQL跟SQL Server也有分区对齐的问题,都是水平切分,大家都允许分区列存在NULL值 这次我们测试SQL Server表分区的分区列的NULL值,究竟NULL值是被存放在哪个区间,以前一直没有注意 测试脚本 --1.创建文件组 ALTER DATABASE [sss] ADD

SQL Server表分区【转】

转自:http://www.cnblogs.com/knowledgesea/p/3696912.html SQL Server表分区 什么是表分区 一般情况下,我们建立数据库表时,表数据都存放在一个文件里. 但是如果是分区表的话,表数据就会按照你指定的规则分放到不同的文件里,把一个大的数据文件拆分为多个小文件,还可以把这些小文件放在不同的磁盘下由多个cpu进行处理.这样文件的大小随着拆分而减小,还得到硬件系统的加强,自然对我们操作数据是大大有利的. 所以大数据量的数据表,对分区的需要还是必要的

SQL Server表分区

什么是表分区 一般情况下,我们建立数据库表时,表数据都存放在一个文件里. 但是如果是分区表的话,表数据就会按照你指定的规则分放到不同的文件里,把一个大的数据文件拆分为多个小文件,还可以把这些小文件放在不同的磁盘下由多个cpu进行处理.这样文件的大小随着拆分而减小,还得到硬件系统的加强,自然对我们操作数据是大大有利的. 所以大数据量的数据表,对分区的需要还是必要的,因为它可以提高select效率,还可以对历史数据经行区分存档等.但是数据量少的数据就不要凑这个热闹啦,因为表分区会对数据库产生不必要的

SQL Server锁分区特性引发死锁解析

原文:SQL Server锁分区特性引发死锁解析 锁分区技术使得SQL Server可以更好地应对并发情形,但也有可能带来负面影响,这里通过实例为大家介绍,分析由于锁分区造成的死锁情形. 前段时间园友@JentleWang在我的博客锁分区提升并发,以及锁等待实例中问及锁分区的一些特性造成死锁的问题,这类死锁并不常见,我们在这里仔细分析下.不了解锁分区技术的朋友请先看下我的锁分区那篇实例. Code(执行测试脚本时请注意执行顺序,说明) 步骤1 创建测试数据 use tempdb go creat

SQL Server 2008 分区函数和分区表详解

SQL Server 2008 分区函数和分区表详解 2012-10-28 20:06 来源:博客园 作者:zhijianliutang 字号:T|T [摘要]本文详细介绍SQL Server 2008 分区函数和分区表,包括查询某个分区.归档数据.添加分区.删除分区等内容. 当我们数据量比较大的时候,我们需要将大型表拆分为多个较小的表,则只访问部门数据的查询就可以更快的运行,基本原理就是,因为要扫描的数据变的更小.维护任务(例如,重新生成索引或备份表)也可以更快的运行. 我们可以再不通过将表物

深入浅出SQL Server 2008 分区函数和分区表

原文:深入浅出SQL Server 2008 分区函数和分区表 当我们数据量比较大的时候,我们需要将大型表拆分为多个较小的表,则只访问部门数据的查询就可以更快的运行,基本原理就是,因为要扫描的数据变的更小.维护任务(例如,重新生成索引或备份表)也可以更快的运行. 我们可以再不通过将表物理放置在多个磁盘驱动器上来拆分表的情况下获取分区.如果将某个表放置在一个物理驱动器上,将相关表放置在另一个驱动器上,则可以提高查询性能,因为当运行涉及表间连接的查询时,多个磁盘头同时读取数据.可以使用SQL Ser

在一个SQL Server表中的多个列找出最大值

在一个SQL Server表中一行的多个列找出最大值 有时候我们需要从多个相同的列里(这些列的数据类型相同)找出最大的那个值,并显示 这里给出一个例子 IF (OBJECT_ID('tempdb..##TestTable') IS NOT NULL) DROP TABLE ##TestTable CREATE TABLE ##TestTable ( ID INT IDENTITY(1,1) PRIMARY KEY, Name NVARCHAR(40), UpdateByApp1Date DATE