SQL Server 当表分区遇上唯一约束(转载)
一、前言
我已经在高兴对服务器创建了表分区并且获得良好性能和自动化管理分区切换的时候,某一天,开发人员告诉我,某表的两个字段的数据不唯一,需要为这两个字段创建唯一索引的时候,这一切就变得不完美了。
列的唯一,这个实际上是一个唯一索引。使用关键字unique建立。
二、背景
我有一个表TestUnique,这个表使用分区方案[Sch_TestUnique_Id],它是以Id做为分区依据列的,这个Id也是一个聚集索引,表中其它索引是跟分区对齐的(创建其它非聚集索引的时候使用了分区方案或者不指定-默认就是分区方案),而且我我这个表很大,我需要定时的进行交换分区(SWITCH PARTITION、滑动窗口、切换分区),表分区的相关信息可参考:SQL Server 表分区实战系列(文章索引)
--创建测试表
CREATE TABLE [dbo].[TestUnique](
[Id] [int] IDENTITY(600000000,1) NOT FOR REPLICATION NOT NULL,
[SiteId] [int] NULL,
[Url] [nvarchar](420) NULL,
[PublishOn] [datetime] NULL,
[AddOn] [datetime] NULL,
CONSTRAINT [PK_Archive] PRIMARY KEY CLUSTERED
(
[Id] ASC
)WITH (PAD_INDEX = ON, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, FILLFACTOR = 100) ON [Sch_TestUnique_Id]([Id])
) ON [Sch_TestUnique_Id]([Id])
GO
现在需要创建SiteId+Url做为一个唯一索引,本来以为这个唯一索引是可以进行分区对齐的,但是却在创建索引的时候遇到错误了。
三、分析
1. 对分区表创建索引时,SQL Server 将使用与该表相同的分区方案和分区依据列自动对索引进行分区。因此,索引的分区方式实质上与表的分区方式相同。这将使索引与表“对齐”。创建唯一索引有下面三种方式:
--方式1
CREATE UNIQUE NONCLUSTERED INDEX [IX_TestUnique_SiteIdUrl]
ON [TestUnique] (SiteId,Url)
消息1908,级别16,状态1,第1 行
列'Id' 是索引'IX_TestUnique_SiteIdUrl' 的分区依据列。唯一索引的分区依据列必须是索引键的子集。
--方式2
ALTER TABLE [dbo].[TestUnique] ADD CONSTRAINT [IX_TestUnique_SiteIdUrl] UNIQUE NONCLUSTERED
(
[SiteId] ASC,
[Url] ASC
)WITH (SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, ONLINE = OFF) ON [Sch_TestUnique_Id]([Id])
消息1908,级别16,状态1,第1 行
列'Id' 是索引'IX_TestUnique_SiteIdUrl' 的分区依据列。唯一索引的分区依据列必须是索引键的子集。
消息1750,级别16,状态0,第1 行
无法创建约束。请参阅前面的错误消息。
--方式3
CREATE UNIQUE NONCLUSTERED INDEX [IX_TestUnique_SiteIdUrl] ON [dbo].[TestUnique]
(
[SiteId] ASC,
[Url] ASC
)WITH (SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = ON, ONLINE = OFF) ON [Sch_TestUnique_Id]([Id])
GO
--测试没有指定分区方案时是否默认使用分区方案
CREATE NONCLUSTERED INDEX [IX_TestUnique_SiteIdUrl] ON [dbo].[TestUnique]
(
[SiteId] ASC,
[Url] ASC
)WITH (SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, ONLINE = OFF)
GO
2. 如果分区依据列不可能包含在唯一键中,则必须使用 DML 触发器,而不是强制实现唯一性。(在需要分区的表中,估计插入的数据量还是比较大的,在这个表使用触发器应该会有性能上的问题吧?)
--测试索引键的子集
CREATE UNIQUE NONCLUSTERED INDEX [IX_TestUnique_SiteIdUrl] ON [dbo].[TestUnique]
(
[Id] ASC,
[SiteId] ASC,
[Url] ASC
)WITH (SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = ON, ONLINE = OFF) ON [Sch_TestUnique_Id]([Id])
上面这条SQL是能成功执行的,不过从业务逻辑上来看,加了唯一的Id值对唯一就没有任何意义了,但是这条SQL告诉我们:当你使用了SiteId做为分区依据列,那么你就可以创建以SiteId+Url的唯一索引。
3. IGNORE_DUP_KEY = ON与IGNORE_DUP_KEY = OFF的区别:
忽略重复键,在创建或修改唯一索引时,可以可设置一个忽略重复键的选项。如果此选项已设置为“是”(ON),当您试图通过添加影响多行的数据来创建重复键(使用 INSERT 语句)时,则不会添加包含重复项的行,不重复的记录会给插入到表中的;如果此选项设置为“否”(OFF),则整个插入操作将失败,并且将回滚所有数据。
4. 如果您预计将通过使用更多分区来扩展索引,或者将会涉及到频繁的分区切换,那么将索引与已分区表对齐将非常重要。有关详细信息,请参阅设计分区以管理数据子集。如果表与其索引对齐,SQL Server 则可以快速高效地切换分区,同时又能维护表及其索引的分区结构。
5. 在下列情况下,独立于基表而单独设计已分区索引(不对齐)很有用:
- 基表未分区。
- 索引键是唯一的,不包含表的分区依据列。
- 您希望基表与使用不同联接列的多个表一起参与组合联接。
四、注意
1. 索引要与其基表对齐,并不需要与基表参与相同的命名分区函数。但是,索引和基表的分区函数在实质上必须相同,即:
- 分区函数的参数具有相同的数据类型;
- 分区函数定义了相同数目的分区;
- 分区函数为分区定义了相同的边界值。
2. 若要启用分区切换,表的所有索引都必须对齐。
3. 如果在创建时指定了不同的分区方案或单独的文件组来存储索引,则 SQL Server 不会将索引与表对齐。
五、总结
1. 如果不需要进行交换分区的情况下,并且你那么幸运让唯一索引列包含了分区依据列的话,你完全可以让唯一与表分区对齐,而且不用担心交换分区的影响;
2. 如果不需要进行交换分区的情况下,唯一索引不包含分区依据列,那就让唯一索引单独使用一个文件组,这样性能也能得到一部分的提升;
3. 如果需要进行交换分区的情况下,唯一索引不包含分区依据列,那就让唯一索引单独使用一个文件组,但是你需要在进行交换分区之前:停止TCP/IP防止进数据,重启服务,删除唯一索引,交换分区,创建唯一索引,启用TCP/IP,重启服务;(貌似这不是个好方法,欢迎大家提供好的方案)
六、参考文献
定义了索引视图时的分区切换
使用分区切换高效传输数据
已分区索引的特殊指导原则(唯一索引)
设计分区以管理数据子集
SQL Server 当表分区遇上唯一约束(转载)的更多相关文章
- 千万级SQL Server数据库表分区的实现
千万级SQL Server数据库表分区的实现 2010-09-10 13:37 佚名 数据库 字号:T | T 一般在千万级的数据压力下,分区是一种比较好的提升性能方法.本文将介绍SQL Server ...
- SQL Server 创建表分区
原文:SQL Server 创建表分区 先准备测试表 CREATE TABLE [dbo].[Employee] ( EmployeeNo ,) PRIMARY KEY, EmployeeName ) ...
- SQL Server 2008 表分区的含义
https://www.cnblogs.com/knowledgesea/p/3696912.html 继续看这个文档 http://www.360doc.com/content/16/0104/11 ...
- SQL Server 2012 表分区
转载于:https://www.cnblogs.com/knowledgesea/p/3696912.html 什么是表分区 一般建立数据库表时,表数据都存放在一个文件里. 但是如果是分区表的话,表数 ...
- SQL Server 创建表
SQL Server 创建表 我们在上一节中完成了数据库的创建,在本节,我们要往这个新的数据库中加入点数据,要想将数据添加到数据库,我们就必须在数据库中添加一个表,接下来来看看具体的操作. 我们的数据 ...
- SQL Server 批量主分区备份(One Job)
一.本文所涉及的内容(Contents) 本文所涉及的内容(Contents) 背景(Contexts) 案例分析(Case) 实现代码(SQL Codes) 主分区完整.差异还原(Primary B ...
- SQL Server 批量主分区备份(Multiple Jobs)
一.本文所涉及的内容(Contents) 本文所涉及的内容(Contents) 背景(Contexts) 案例分析(Case) 方案一(Solution One) 方案二(Solution Two) ...
- [SQL]SQL Server数据表的基础知识与增查删改
SQL Server数据表的基础知识与增查删改 由张晨辉(学生) 于19天 前发表 | 阅读94次 一.常用数据类型 .整型:bigint.int.smallint.tinyint .小数:decim ...
- Sql server 系统表
sql server系统表详细说明 SQL Server 用户库中系统表说明 名称 说明 备注 syscolumns 每个表和视图中的每列在表中占一行,存储过程中的每个参数在表中也占一行. sys ...
随机推荐
- Mysql 锁机制和事务
InnoDB 锁机制 InnoDB存储引擎支持行级锁 其大类可以细分为共享锁和排它锁两类 共享锁(S):允许拥有共享锁的事务读取该行数据.当一个事务拥有一行的共享锁时,另外的事务可以在同一行数据也获得 ...
- 详解C#特性和反射(二)
使用反射(Reflection)使得程序在运行过程中可以动态的获取对象或类型的类型信息,然后调用该类型的方法和构造函数,或访问和修改该类型的字段和属性:可以通过晚期绑定技术动态的创建类型的实例:可以获 ...
- Selenium3自动化问题二:各chrome版本对应的chromedriver版本
一:问题说明 最近用到selenium3在火狐浏览器中执行自动化脚本,遇到了一些问题,最后解决方案中占比最多的就是浏览器和驱动版本不一致导致的,故这里给出chrome.firefox驱动的不同版本对应 ...
- python的Web框架:Django路由系统以及模板导入
Django的路由系统 当一个请求来到时 当一个请求来到时 1.首先到项目目录下的urls.py(根URLconf模块)中,查找路由规则: 2.根URELcof模块,里面定义了 urlpatterns ...
- Android系统版本、Platform版本、SDK版本、gradle修改
虽然之前分析了gradle,但是在eclipse导入Android studio的时候,各个版本出现的问题还是很模糊,下面对各种版本进行一下说明: 参考资料: https://developer.an ...
- [NOI 2015]寿司晚宴
Description 题库链接 给定 \(2\sim n\) 一共 \(n-1\) 个数字,第一个人选择一些数字,第二个人选择一些数字,要求第一个人选的任意一个数字和第二个人选择的任意一个数字都互质 ...
- [转]DevOps实战:百度持续交付体系与最佳实践大解密!
本文转自:http://dbaplus.cn/news-21-471-1.html “互联网+”时代,软件产品要想满足快速增长的用户需求,高效.快速的迭代转型必不可少,面对时刻发生改变的互联网及业务模 ...
- Hibernate高效查询,只查询部分/指定字段
公司使用 DetachedCriteria detachedCriteria = DetachedCriteria.forClass(PeBulletin.class); detachedCriter ...
- vue-infinite-loading2.0 中文文档
简介 这是一个使用在Vue.js中的无限滚动插件,它可以帮助你快速创建一个无限滚动列表. 特点 移动端支持友好 兼容任何一个可以滚动的元素 有不同的旋转器可以作为加载动画 支持加载后显示结果 支持两个 ...
- 查找具有特定属性的元素 (XPath-LINQ to XML)
XElement doc = XElement.Parse( @"<Root> <Child1>1</Child1> <Child2 Select= ...