参考文档 https://msdn.microsoft.com/zh-cn/library/ms345146(SQL.90).aspx
     http://blog.sina.com.cn/s/blog_4c8f1ac20100rhu7.html

  分区是为了改善大型表以及具有各种访问模式的表的可伸缩性和可管理性。分区使我们不需要将所有数据放到一个位置,但是需要创建和管理许多对象。当所有数据位于一个表中,删除旧数据需要对表及其相关索引进行逐行处理。删除数据的过程将创建大量的日志活动。但是如果使用分区,删除相同数量的数据只需从分区表中删除特定的分区,然后删除或截断独立的表。

SQLServer分区过程:

1、创建文件组

alter database OrderDB add filegroup [FG_OrderDetail_01];
alter database OrderDB add filegroup [FG_OrderDetail_02];

2、创建文件组文件

如果有多块硬盘,可以将每个文件组中的文件分配到每个硬盘上,这样可实现分布式磁盘I/O,数据库引擎就可以同时并行检索多块硬盘,提高并发读写速度。

alter database OrderDB add file(
name=N'FG_OrderDetail_01'
,filename=N'C:\Program Files\Microsoft SQL Server\MSSQL.1\MSSQL\FTData\FG_OrderDetail_01_data.ndf'
,size=5MB
)to filegroup [FG_OrderDetail_01]; alter database OrderDB add file(
name=N'FG_OrderDetail_02'
,filename=N'C:\Program Files\Microsoft SQL Server\MSSQL.1\MSSQL\FTData\FG_OrderDetail_02_data.ndf'
,size=5MB
)to filegroup [FG_OrderDetail_02];

3、创建分区函数

create partition function [partition_order_date](datetime)
as range left for values('20170131 23:59:59.997', '20170228 23:59:59.997')

4、创建分区方案 (若要切换分区需预留一个空分区,该例子以PRIMARY 文件组作为第3个空分区)

create partition scheme [scheme_order_date] as partition [partition_order_date]
to ([FG_OrderDetail_01], [FG_OrderDetail_02], [PRIMARY])

5、在分区方案下建表

CREATE TABLE [dbo].[order_detail](
[order_id] int NOT NULL,
[product_id] int NOT NULL,
[order_qty] int NOT NULL,
[unit_price] decimal(24,8) NOT NULL,
[total_amount] decimal(24,8) NOT NULL,
[order_date] datetime NOT NULL
CONSTRAINT OrderDetailDateCK CHECK ([order_date] >= '20170101' AND [order_date] < '20170301')
) ON [scheme_order_date]([order_date])

6、插入数据

INSERT dbo.[order_detail](order_id, total_amount, order_date)
SELECT o.PurchaseOrderID, o.TotalAmount, o.OrderDate
FROM dbo.PurchaseOrderDetail as o
WHERE (o.[OrderDate] >= '20170101' AND o.[OrderDate] < '20170301')

7、在分区方案下重建索引

IF EXISTS(SELECT * FROM sysobjects WHERE name='pk_order_detail' and xtype='PK')
ALTER TABLE dbo.order_detail DROP CONSTRAINT [pk_order_detail];
ALTER TABLE dbo.order_detail ADD CONSTRAINT [pk_order_detail]
PRIMARY KEY CLUSTERED(order_id, product_id) ON [scheme_order_date]([order_date]);
IF EXISTS (SELECT 1 FROM sysindexes WHERE name = 'idx_order_detail')
DROP INDEX [idx_order_detail] ON dbo.order_detail;
CREATE NONCLUSTERED INDEX [idx_order_detail] ON dbo.order_detail(order_date);

8、查看分区情况

(1)查看每个分区的具体数据

SELECT $partition.partition_order_date(o.order_date) AS [PartitionNo], count(*) AS [RowsInPartition]
FROM dbo.order_detail AS o
GROUP BY $partition.partition_order_date(o.order_date)
ORDER BY [PartitionNo]

(2)查看所有使用分区的表

Select s.name As SchemaName, t.name As TableName
From sys.tables t
Inner Join sys.schemas s On t.schema_id = s.schema_id
Inner Join sys.partitions p on p.object_id = t.object_id
Where p.index_id In (0, 1)
Group By s.name, t.name Having Count(*) > 1 Order By s.name, t.name;

(3)查看分区表的所有分区

SELECT * FROM sys.partitions WHERE OBJECT_NAME(OBJECT_ID)='order_detail';

  上图表示order_details的聚集索引分为3个分区。index_id  0: heap(没有聚集索引的堆表),1:Clustered Index, 2:NonClustered Index

9、分区表连接查询(分区消除,两个表采用同一个分区方案)

  表和索引对齐

  当多个表使用同一个函数(但不一定使用同一个架构)时,此概念称为对齐。SQL Server 将按类似的方式对具有相同分区键的行进行分组。
  具有相同分区键值的相关数据将被放置到同一个文件中,而将必要的数据隔离出来以便进行连接。如果来自多个表的相关行都按照相同的方式进行分区,SQL Server 则可以连接分区,而无需在整个表或多个分区中(如果表使用了不同的分区函数)搜索匹配的行。在这种情况下,不仅可以对齐对象(因为它们使用相同的键),还可以按存储位置对齐(因为相同的数据位于相同的文件中)。

  当表和索引按照相同的顺序使用相同的分区函数和列时,表和索引将对齐。使用相同的函数对表及其索引进行分区通常可以优化性能。当表及其索引对齐后,SQL Server 则可以更有效地将分区移入和移出分区表,因为所有相关的数据和索引都使用相同的算法进行划分。

  如果定义表和索引时不仅使用了相同的分区函数,还使用了相同的分区架构,则这些表和索引将被认为是按存储位置对齐。按存储位置对齐的一个优点是,相同边界内的所有数据都位于相同的物理磁盘上。在这种情况下,可以单独在某个时间段内执行备份操作,还可以根据数据的变化在备份频率和备份类型方面改变您的策略。如果连接或收集了相同文件或文件组中的表和索引,则可以发现更多的好处。SQL Server 可以通过在多个分区中并行操作来获益。在按存储位置对齐和多 CPU的情况下,每个处理器都可以直接处理特定的文件或文件组,而不会与数据访问产生任何冲突,因为所有需要的数据都位于同一个磁盘上。这样,可以并行运行多个进程,而不会相互干扰。

对存储位置对齐的分区表进行连接查询可以大大提高效率

SELECT o.order_id, o.order_date, o.vendor_id, od.product_id, od.order_qty
FROM dbo.order AS o
INNER JOIN dbo.order_detail AS od ON o.order_id = od.order_id AND o.order_date = od.order_date
WHERE o.order_date >= '' AND o.order_date <= '20170131 11:59:59.997'

图二所示,Constant Scan用于获取分区ID,  Inner Join将两个分区数据集连接起来。SQL Server 正在消除所有不需要的分区,并且只选择包含正确数据的分区。把光标悬停在“Constant Scan”上会显示Argument参数 VALUES(((1)))),这代表分区号 。

    

 10、删除分区

可参考 https://appliedsql.net/2013/10/08/how-to-remove-a-table-partitioning-in-sql-server/

若表存在聚集索引,可直接去掉聚集索引对分区方案的依赖,否则需要直接删除表

IF EXISTS(SELECT * FROM sysobjects WHERE name='pk_order_detail' and xtype='PK')
ALTER TABLE dbo.order_detail DROP CONSTRAINT [pk_order_detail];
ALTER TABLE dbo.order_detail ADD CONSTRAINT [pk_order_detail] PRIMARY KEY CLUSTERED(order_id, product_id) ON [PRIMARY];

删除分区方案和分区函数

IF EXISTS (SELECT 1 FROM sys.partition_schemes WHERE name = 'scheme_order_date')
DROP PARTITION SCHEME scheme_order_date;
IF EXISTS (SELECT 1 FROM sys.partition_functions WHERE name = 'partition_order_date')
DROP PARTITION FUNCTION partition_order_date;

删除分区后聚集索引只剩一个分区

滑动窗口方案:

  分区表分区切换并没有真正去移动数据,而是 SQL Server 在系统底层改变了表的元数据。因此分区表分区切换是高效、快速、灵活的。利用分区表的分区切换功能,我们可以快速加载数据到分区表。卸载分区数据到普通表,然后 truncate 普通表,以实现快速删除分区表数据。快速归档不活跃数据到历史表。   

  如果您打算在滑动窗口方案中管理数据,通常需要有一个可以拆分的空分区,以便放置新数据。移入和移出表的过程非常快,而且准备工作可以在分区表外完成。在SQL Server 2005的解决方案中:您可以轻松地移入新填充的分区(作为现有分区架构的额外分区),还可以移出任何旧分区。整个过程只需要很短的时间即可完成,通过使用并行批量加载和并行索引建立,还可以进一步提高效率。更重要的是,因为分区是在表范围之外进行管理的,所以添加分区之前不会对所查询的表造成任何影响。添加一个分区通常只需要几秒钟。当下一个月的数据(在本例中是 2017年03月)可用时,将按特定的操作顺序使用现有的文件组移入和移出数据。

一、管理将要移入的分区的分段表

1. 创建分段表

  为了获取更好的性能,将数据加载到未建立索引且未应用约束的堆中,然后在将表移入分区表之前添加约束(参见步骤 3)WITH CHECK。

CREATE TABLE [dbo].[order_detail_201703](
[order_id] int NOT NULL,
[product_id] int NOT NULL,
[order_qty] int NOT NULL,
[unit_price] decimal(24,8) NOT NULL,
[total_amount] decimal(24,8) NOT NULL,
[order_date] datetime NOT NULL
) ON [FG_OrderDetail_01]

2. 加载包含数据的分段表。如果文件是一致的,此过程应该通过 BULK INSERT 语句执行。

  如果要将数据单独放到一个新创建的(空)且未建立索引(堆)的表中,则可以先加载数据,而在加载数据之后建立索引。通常情况下,使用这种架构可以获得十倍或更好的性能。实际上,通过加载未建立索引的表可以利用多个 CPU,因此可以并行加载多个数据文件或从同一个文件中加载多个数据块(通过开始和结束行位置来定义)。

3. 加载数据后,即可添加约束。

ALTER TABLE [dbo].[order_detail_201703]
WITH CHECK ADD CONSTRAINT OrderDetailDateCK
CHECK ([order_date] >= '' AND [order_date] <= '20170331 23:59:59.997')

4. 为分段表建立索引。分段表必须与其要移入的表(成为该表的一个分区)具有相同的群集索引。

ALTER TABLE [dbo].[order_detail_201703]
ADD CONSTRAINT pk_order_detail PRIMARY KEY CLUSTERED (order_id, product_id) ON [FG_OrderDetail_01]

二、创建将要移出的分区的分段表

1. 创建第二个分段表。这是一个空表,用于存储移出的分区中的数据

CREATE TABLE [dbo].[order_detail_201701](
[order_id] int NOT NULL,
[product_id] int NOT NULL,
[order_qty] int NOT NULL,
[unit_price] decimal(24,8) NOT NULL,
[total_amount] decimal(24,8) NOT NULL,
[order_date] datetime NOT NULL
) ON [FG_OrderDetail_01]

2. 为分段表建立索引。分段表必须与其要移入的表(成为该表的一个分区,而该分区将成为此表)具有相同的群集索引。

ALTER TABLE [dbo].[order_detail_201701]
ADD CONSTRAINT pk_order_detail PRIMARY KEY CLUSTERED (order_id, product_id) ON [FG_OrderDetail_01] 

三、移出旧数据,并将新数据移入分区表。

1. 移出旧数据,放入第二个分段表中。

ALTER TABLE [dbo].[order_detail] SWITCH PARTITION 1 TO [dbo].[order_detail_201701]

2. 更改分区函数以删除2017年1月的边界点。此操作还会删除文件组与分区架构之间的关联。具体来说,FG_OrderDetail_01将不再是分区架构的一部分。

ALTER PARTITION FUNCTION Fun_OrderDetail() MERGE RANGE ('20170131 23:59:59.997')

3. 滚动现有2个分区的新数据,使FG_OrderDetail_01成为“下一个使用的”分区,此分区将是下一个用于拆分的分区。

ALTER PARTITION SCHEME Sch_OrderDetail NEXT USED [FG_OrderDetail_01]

4. 更改分区函数,为2017年3月添加新的边界点。

ALTER PARTITION FUNCTION Fun_OrderDetail() SPLIT RANGE ('20170331 23:59:59.997')

5. 更改基础表的约束定义(如果存在),以允许新范围的数据。
  因为添加约束的代价可能很昂贵(需要验证数据),所以最好的做法是继续扩大日期范围,而不是删除并重新创建约束。现在,只存在一个约束(OrderDetailDateCK),但以后将存在两个约束。

ALTER TABLE [dbo].[order_detail] ADD CONSTRAINT OrderDetailMinDateCK CHECK ([order_date] >= '')
ALTER TABLE [dbo].[order_detail] ADD CONSTRAINT OrderDetailMaxDateCK CHECK ([order_date] < '')
ALTER TABLE [dbo].[order_detail] DROP CONSTRAINT OrderDetailDateCK

6. 从第一个分段表中移入新数据。

ALTER TABLE [dbo].[order_detail_201703] SWITCH TO [dbo].[order_detail] PARTITION 2

四、删除分段表

DROP TABLE [dbo].[order_detail_201701]
DROP TABLE [dbo].[order_detail_201703]

五、备份文件组

  最后一步备份的对象是根据您的备份策略选择的。如果选择了基于文件或文件组的备份策略,则应执行文件或文件组备份。如果选择了基于整个数据库的备份策略,则可以执行完整数据库备份或差异备份。

BACKUP DATABASE OrderDB FILEGROUP = 'FG_OrderDetail_01' TO DISK = 'C:\OrderDB\OrderDB.bak'

总结 

  SQL Server 允许根据范围进行分区,还允许将表和索引都设计为使用相同的架构,以便更好地对齐。SQL Server 2005 已经考虑了如何简化分区的管理、开发和使用。它在性能和可管理性方面有以下优点:

  • 简化了需要进行分区以改善性能或可管理性的大型表的设计和实现。

  • 将数据加载到现有分区表的新分区中时,最大程度地减少了对其他分区中的数据访问的影响。

  • 将数据加载到现有分区表的新分区中时,性能相当于将同样的数据加载到新的空表中。

  • 在存档和/或删除分区表的一个分区时,最大程度地减少了对表中其他分区的访问的影响。

  • 允许通过将分区移入和移出分区表来维护分区。

  • 提供了更好的伸缩性和并行性,可以对多个相关表执行大量操作。

  • 改善了所有分区的性能。

  • 缩短了查询优化时间,因为不需要单独优化每个分区。

附加:合理组织数据库文件和文件

   1.主文件组完全独立,只存放系统对象,所有的用户对象都不在主文件组中,主文件组也不应该设为默认文件组,将系统对象和用户对象分开可以获得更好的性能
   2.如果有多块硬盘,可以将每个文件组中的文件分配到每个硬盘上,这样可实现分布式磁盘I/O,提高读写速度
   3.将访问频繁的表及其索引放到一个独立的文件组中,这样可以提高读取数据和索引的速度.
   4.将访问频繁的包含TEXT和IMAGE数据类型的列的表放到一个单独的文件组中,最好将 TEXT 和IMAGE放在一个独立的硬盘中
   5.将事务日志文件放到一个独立的硬盘上,千万不要和DATEFILE共用一个硬盘;日志操作属于密集型操作.
   6.将'只读'表单放到一个单独的文件组中,同样,'只写'也是
   7.不要过度使用'自动增长',设置自动增长值为一个合适的值,如:一周,同样,'自动收缩'也是如此

sqlserver 数据库表分区的更多相关文章

  1. 千万级SQL Server数据库表分区的实现

    千万级SQL Server数据库表分区的实现 2010-09-10 13:37 佚名 数据库 字号:T | T 一般在千万级的数据压力下,分区是一种比较好的提升性能方法.本文将介绍SQL Server ...

  2. SQLSERVER数据库表各种同步技术

    1 --SQLSERVER数据库表各种同步技术 减少SQLServer中每次的同步数据量 2 3 --说到数据库,我就不由地想到同步数据,如何尽可能地减少每次的同步数据量,以此来提高同步效率,降低对网 ...

  3. Oracle数据库表分区

    一.Oracle数据库表分区概念和理解         1.1.已经存在的表没有方法可以直接转化为分区表.         1.2.不在分区字段上建立分区索引,在别的字段上建立索引相当于全局索引.效率 ...

  4. zabbix(4)数据库表分区优化

    一.zabbix 数据库存储 zabbix-server将采集到的数据存储在数据库(mysql.oracle等),而数据存储的大小与每秒处理的数量量有关,因此数据存储取决于以下两个因数: (1)Req ...

  5. SqlServer数据库表生成C# Model实体类SQL语句——补充

    在sql语句最前边加上  use[数据库名] 原链接:https://www.cnblogs.com/jhli/p/11552105.html   --[SQL骚操作]SqlServer数据库表生成C ...

  6. MySQL数据库表分区功能详解

    1.什么是表分区? mysql数据库中的数据是以文件的形势存在磁盘上的,默认放在/mysql/data下面(可以通过my.cnf中的datadir来查看),一张表主要对应着三个文件,一个是frm存放表 ...

  7. mysql数据库表分区详解(数量过大的数据库表通过分区提高查询速度)

    这篇文章主要介绍了MySQL的表分区,例如什么是表分区.为什么要对表进行分区.表分区的4种类型详解等,需要的朋友可以参考下 一.什么是表分区通俗地讲表分区是将一大表,根据条件分割成若干个小表.mysq ...

  8. SqlServer数据库表导入SqlLite数据库表保持日期时间类型字段的格式

    在写查询功能的过程中遇到一个这样的问题:按日期范围查询,sql语句是:where dt>=用户选择起始日期&&dt<=用户选择结束日期.数据库中的数据如图1,我选择的测试数 ...

  9. Zabbix数据库表分区

    zabbix的监控主机数量将近300,且运行了一年时间了,最近zabbix server服务监控历史数据等服务不断自身告警.查询性能也变得很低 关于历史数据的两个参数,在zabbix server的配 ...

随机推荐

  1. C++面向对象类的实例题目八

    题目描述: 编写一个程序输入3个学生的英语和计算机成绩,并按照总分从高到低排序.要求设计一个学生类Student,其定义如下: 程序代码: #include<iostream> using ...

  2. SpringBoot12 QueryDSL02之利用QueryDSL实现多表关联查询

    1 业务需求 有的系统业务逻辑比较复杂,存在着多表关联查询的的情况,查询的内容不仅仅是单张表的的内容而是多张表的字段组合而成的,直接使用SplringDataJPA实现是比较复杂的,但是如果使用Que ...

  3. ROS Learning-002 beginner_Tutorials 如何添加ROS环境变量 和 如何更新ROS源代码

    ROS Indigo beginner_Tutorials 之 添加环境变量 和 更新ROS源代码的命令 我使用的虚拟机软件:VMware Workstation 11 使用的Ubuntu系统:Ubu ...

  4. poj2287 Tian Ji -- The Horse Racing

    传送门 分析 这个题和传统的田忌赛马不一样的地方就是多了平局情况,所有我们不难想到要用dp.我们先将两人的马均降序排列,用dpij表示考虑前i匹马,田忌有几匹马是按从大到小的顺序从头取的(剩下的是从尾 ...

  5. WOJ 18 动态无向图

    一开始我是不会写的,后来点开了题解: 无话可说……那就写吧……然而第一发跑成暴力分,后来加了一个优化:就是在询问里面提到过的边都不用再加了. 然后……然后就过了呀…… 其实还有面向数据的编程的骚操作… ...

  6. Socket编程--并发server

    Socket地址复用 int getsockopt(int sockfd, int level, int optname, void *optval, socklen_t *optlen); int ...

  7. CSS+DIV网页样式布局实战从入门到精通 中文pdf扫描版

    CSS+DIV网页样式布局实战从入门到精通通过精选案例引导读者深入学习,系统地介绍了利用CSS和DIV进行网页样式布局的相关知识和操作方法. 全书共21章.第1-5章主要介绍网页样式布局的基础知识,包 ...

  8. 内存不足导致的java.lang.OutOfMemoryError: java heap space引出java工程启动参数设置

    今天做分类实验,生成了190m的kernel文件,在读到svm中的时候跳出了java.lang.OutOfMemoryError: java heap space异常.随便搜了一下,发现与eclips ...

  9. WPF之MVVM模式(3)

    有种想写一个MVVM框架的冲动!!! 1.Model中的属性应不应该支持OnPropertyChanged事件? 不应该.应该有ViewModel对该属性进行封装,由ViewModel提供OnProp ...

  10. Layer 父子页面之间的交互

    父页面获取子页面 var body = layer.getChildFrame('body',index);//建立父子联系 body.find("#parameter").val ...