在SQL Server中,对超级大表做数据归档,使用select和delete命令是十分耗费CPU时间和Disk空间的,SQL Server必须记录相应数量的事务日志,而使用switch操作归档分区表的老数据,十分高效,switch操作不会移动数据,只是做元数据的置换,因此,执行分区切换操作的时间是非常短暂的,几乎是瞬间完成,但是,在做分区切换时,源表和靶表必须满足一定的条件:

  • 表的结构相同:列的数据类型,可空性(nullability)相同;
  • 索引结构必须相同:索引键的结构,聚集性,唯一性,列的可空性必须相同;
    • 主键约束:如果源表存在主键约束,那么靶表必须创建等价的主键约束;
    • 唯一约束:唯一约束可以使用唯一索引来实现;
    • 索引键的结构:索引键的顺序,包含列,唯一性,聚集性都必须相同;
  • 存储的数据空间(data space)相同:源表和靶表必须创建在相同的FileGroup或Partition Scheme上;

分区切换是将源表中的一个分区,切换到靶表(target_table)中,靶表可以是分区表,也可以不是分区表,switch操作的语法是:

ALTER TABLE schema_name . table_name
SWITCH [ PARTITION source_partition_number_expression ]
TO target_table [ PARTITION target_partition_number_expression ]

一,创建示例数据

-- create parition function
create partition function pf_int_left (int)
as range left
for values (10,20); --create partition scheme
create partition scheme ps_int_left
as
partition pf_int_left
all to ([primary]); --create partitioned table
create table dbo.dt_partition
(
ID int null,
Code int null
)
on ps_int_left (id) --Create staging table
create table dbo.dt_SwitchStaging
(
ID int null,
Code int null
)
on [primary]

创建靶表 dt_SwitchStaging,用于存储分区表的数据

二,源表和目标表的结构必须相同

1,数据列的可空性必须相同(nullability)

由于靶表的ID列是非空的(not null),源表的ID列是可空的(null),可空性不同,在切换分区时,SQL Server会抛出错误消息:

alter table dbo.dt_SwitchStaging
alter column ID int not null; --swith partition 2 to staging table
alter table dbo.dt_partition
switch partition 2
to dbo.dt_SwitchStaging

ALTER TABLE SWITCH statement failed because column 'ID' does not have the same nullability attribute in tables 'dbo.dt_partition' and 'dbo.dt_SwitchStaging'.

2,数据列的数据类型必须相同

在执行分区切换时,源表和靶表的数据类型必须相同,即使数据类型相兼容,SQL Server会抛出错误消息:

alter table  dbo.dt_SwitchStaging
alter column ID bigint null

ALTER TABLE SWITCH statement failed because column 'ID' has data type int in source table 'dbo.dt_partition' which is different from its type bigint in target table 'dbo.dt_SwitchStaging'.

三,隐式的Check约束,实现分区的可空属性

分区列(Partition Column)允许为NULL,SQL Server在分区时,将NULL值作为最小值,存储在最左边的第一个分区中,其Partition Number是1。

Any data with a NULL in the partition column will reside in the leftmost partition. NULL is considered smaller than the minimum value of the data type’s values.

分区函数(Partition Function)定义分区列(Partition Column)在每一个分区的取值区间(Value Range),在SQL Server内部,取值区间是使用Check约束来实现的,每一个Partition都有一个check 约束,用于限定Partition column的取值范围:

  • Partition Number=1,Partition column允许存在null;
  • 其他Partition,Partition column不允许存在null;

对于Unknown值,Check约束认为逻辑结果是True,例如,check(ID>1 and ID<10), 如果ID=Null,那么表达式ID>1 and ID<10 返回Unknown(或null),但是,Check约束返回的结果是True,即不违反check约束。

四,表的索引结构必须相同,唯一性和聚集性也必须相同

在执行分区切换时,表的索引结构,唯一性和聚集性必须相同,在SQL Server中,使用unique index 实现unique 约束的唯一性。

1,索引的聚集性

在分区表上创建一个聚集索引(clustered index),在切换分区时,SQL Server抛出错误信息,要求靶表必须创建聚集索引

--create clustered index
create clustered index cix_dt_partition_ID
on dbo.dt_partition(ID)

ALTER TABLE SWITCH statement failed. The table 'dbo.dt_partition' has clustered index 'cix_dt_partition_ID' while the table 'dbo.dt_SwitchStaging' does not have clustered index.

2,唯一约束

在分区表上创建唯一聚集约束(unique clustered),在切换分区时,SQL Server抛出错误消息,要求靶表必须创建唯一索引

alter table dbo.dt_partition
add constraint UQ__dt_partition_ID_Code
unique clustered(ID,Code)

ALTER TABLE SWITCH statement failed. The table 'dbo.dt_partition' has clustered index 'UQ__dt_partition_ID_Code' while the table 'dbo.dt_SwitchStaging' does not have clustered index.

Workaround1:在靶表上创建唯一聚集索引(unique clustered),而不是创建unique clustered 约束,switch 成功;

--create unique clustered index
create unique clustered index ucix_dt_SwitchStaging_ID_Code
on dbo.dt_SwitchStaging(ID,Code)

Workaround2:在靶表上创建unique clustered 约束,switch 成功;

3,主键约束

在创建Primary key 约束时,主键列是不可空的

--drop table
drop table dbo.dt_partition
go
drop table dbo.dt_SwitchStaging
GO
--create partitioned table
create table dbo.dt_partition
(
ID int not null,
Code int null,
)
on PS_int_Left (ID)
go
--Create staging table
create table dbo.dt_SwitchStaging
(
ID int not null,
Code int null
)
on [primary]
go

为分区表创建主键约束,使用唯一聚集索引(unique clustered)实现,跟唯一聚集约束的唯一区别是唯一约束列允许为NULL

alter table dbo.dt_partition
add constraint PK__dt_partition_ID
primary key clustered(ID)

将分区表的第二个分区切换到靶表,SQL Server抛出错误信息,要求靶表必须创建唯一聚集索引,注意,不是创建聚集主键;

--swith partition 2 to staging table
alter table dbo.dt_partition
switch partition 2
to dbo.dt_SwitchStaging

ALTER TABLE SWITCH statement failed. The table 'dbo.dt_partition' has clustered index 'PK__dt_partition_ID' while the table 'dbo.dt_SwitchStaging' does not have clustered index.

在靶表上创建唯一聚集索引,在执行分区切换时,SQL Server抛出错误消息:没有等价的索引,这是因为聚集主键创建的索引是唯一的,聚集的,非空的,而唯一聚集索引是唯一的,聚集的,可空的,两者不是完全等价的。

--create unique clustered index
create unique clustered index cix_dt_SwitchStaging_ID
on dbo.dt_SwitchStaging(ID)

ALTER TABLE SWITCH statement failed. There is no identical index in source table 'dbo.dt_partition' for the index 'cix_dt_SwitchStaging_ID' in target table 'dbo.dt_SwitchStaging' .

在靶表上创建聚集主键,switch成功

--add primary key clustered constraint
alter table dbo.dt_SwitchStaging
add constraint PK__dt_SwitchStaging_ID
primary key clustered(ID)

五,总结

在执行分区操作时,要求源表和靶表必须满足:

  • 表的结构相同:列的数据类型,可空性(nullability)相同;
  • 索引结构必须相同:索引键的结构,聚集性,唯一性,列的可空性必须相同;
    • 主键约束:如果源表存在主键约束,那么靶表必须创建等价的主键约束;
    • 唯一约束:唯一约束可以使用唯一索引来实现;
    • 索引键的结构:索引键的顺序,包含列,唯一性,聚集性都必须相同;
  • 存储的数据空间(data space)相同:源表和靶表必须创建在相同的FileGroup或Partition Scheme上;

参考文档:

ALTER TABLE (Transact-SQL)

Partition3:分区切换(Switch)的更多相关文章

  1. Partition:分区切换(Switch)

    在SQL Server中,对超级大表做数据归档,使用select和delete命令是十分耗费CPU时间和Disk空间的,SQL Server必须记录相应数量的事务日志,而使用switch操作归档分区表 ...

  2. SQL Server 2005 分区表实践——分区切换

    本文演示了 SQL Server 2005 分区表分区切换的三种形式: 1. 切换分区表的一个分区到普通数据表中:Partition to Table: 2. 切换普通表数据到分区表的一个分区中:Ta ...

  3. Partition--使用分区切换来增加修改列的自增属性

    使用分区来将非自增表改为自增表 ------------------------------------------------- --创建测试表TestTable001和TestTable002 C ...

  4. 'ALTER TABLE SWITCH' 语句失败。表'MGXXX.dbo.user_XXX' 已分区,但 索引'ix_user_XXX_user_id' 未分区。

    问题描述: 今天在做分区切换的时候把旧log数据切到clear表,遇到了这个问题,顺便做下笔记记录一下解决方法 'ALTER TABLE SWITCH' 语句失败.表'MGXXX.dbo.user_X ...

  5. 优化SQLServer--表和索引的分区(二)

    简介 之前一篇简单的介绍了语法和一些基本的概念,隔了一段时间,觉得有必要细致的通过实例来总结一下这部分内容.如之前所说,分区就是讲大型的对象(表)分成更小的块来管理,基本单位是行.这也就产生了很大优势 ...

  6. (一)SQL Server分区详解Partition(目录)

    一.SQL Server分区介绍 在SQL Server中,数据库的所有表和索引都视为已分区表和索引,默认这些表和索引值包含一个分区:也就是说表或索引至少包含一个分区.SQL Server中数据是按水 ...

  7. SQL Server 解读【已分区索引的特殊指导原则】(1)- 索引对齐

    一.前言 在MSDN上看到一篇关于SQL Server 表分区的文档:已分区索引的特殊指导原则,如果你对表分区没有实战经验的话是比较难理解文档里面描述的意思.这里我就里面的一些概念进行讲解,方便大家的 ...

  8. (四)SQL Server分区管理

    一.拆分分区(SPLIT) 在已有分区上添加一个新分区. 如下图所示,将分区03拆分成03和04分区,拆分方式先锁定旧03分区的所有数据,后将旧03分区相关数据迁移到分区04,最后删除旧03上的对应分 ...

  9. 优化SQLServer——表和分区索引(二)

    简介     之前一篇简单的介绍了语法和一些基本的概念,隔了一段时间,觉得有必要细致的通过实例来总结一下这部分内容.如之前所说,分区就是讲大型的对象(表)分成更小的块来管理,基本单位是行.这也就产生了 ...

随机推荐

  1. 用烂点子打破沉默的"麦当劳理论"

    "麦当劳"理论是啥? 讨论周末聚餐去哪儿的时候,朋友们往往太过顾及彼此的想法,犹豫着等待其他人做决定. 当谁也不愿说出提议的时候, 我往往会耍一个花招:推荐去麦当劳吃. 宝贵的休息 ...

  2. EntityFramework Code-First 简易教程(三)-------数据库初始化

    现在我们来学习,当数据库初始化的时候,Code First怎样设置数据库的名字. 下面的图显示了数据库初始化的工作流程,根据传入给context基类的构造函数的参数来初始化: 根据上面的图,conte ...

  3. man -k : nothing appropriate.

    ➜ workplace man -k zip zip: nothing appropriate. 出现这种情况,是索引库没有建立. man 和 whatis 共用一个索引库的. 我们使用  man w ...

  4. JDOM 操作XML

    http://www.cnblogs.com/hoojo/archive/2011/08/11/2134638.html 可扩展标记语言——eXtensible Markup Language 用户可 ...

  5. Windows XP添加硬盘后系统不能识别(没有任何反应)

    解决方法: 1.右键我的电脑--管理--设备管理器--IDE ATA/ATAPI控制器,启用次要IDE通道和主要IDE通道,打开属性,在高级设置里,将设备类型设置为自动检测,重启. 2.硬盘格式为GP ...

  6. VPC见解

    VPC是什么? VPC:Virtual  Private  Cloud,即虚拟私有云.讨论VPC时,我们可以从两个方面来讨论: 从服务的角度来看:VPC是一种云,但是这个云不属于我们常见的公有云.私有 ...

  7. Docker容器学习与分享08

    Docker容器网络 Docker除了默认创建的三种网络外,还可以自定义网络. 首先创建一个bridge类型的网络,使用docker network create命令. [root@promote ~ ...

  8. 为什么ConcurrentHashMap的读操作不需要加锁?

    我们知道,ConcurrentHashmap(1.8)这个并发集合框架是线程安全的,当你看到源码的get操作时,会发现get操作全程是没有加任何锁的,这也是这篇博文讨论的问题--为什么它不需要加锁呢? ...

  9. Spring IOC容器创建bean过程浅析

    1. 背景 Spring框架本身非常庞大,源码阅读可以从Spring IOC容器的实现开始一点点了解.然而即便是IOC容器,代码仍然是非常多,短时间内全部精读完并不现实 本文分析比较浅,而完整的IOC ...

  10. Angular2学习笔记(1)——Hello World

    1. 写在前面 之前基于Electron写过一个Markdown编辑器.就其功能而言,主要功能已经实现,一些小的不影响使用的功能由于时间关系还没有完成:但就代码而言,之前主要使用的是jQuery,由于 ...