一、前言


我已经在高兴对服务器创建了表分区并且获得良好性能和自动化管理分区切换的时候,某一天,开发人员告诉我,某表的两个字段的数据不唯一,需要为这两个字段创建唯一索引的时候,这一切就变得不完美了。
列的唯一,这个实际上是一个唯一索引。使用关键字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.      索引要与其基表对齐,并不需要与基表参与相同的命名分区函数。但是,索引和基表的分区函数在实质上必须相同,即:

  1. 分区函数的参数具有相同的数据类型;
  2. 分区函数定义了相同数目的分区;
  3. 分区函数为分区定义了相同的边界值。

2.      若要启用分区切换,表的所有索引都必须对齐。
3.      如果在创建时指定了不同的分区方案或单独的文件组来存储索引,则 SQL Server 不会将索引与表对齐。

五、总结


1.      如果不需要进行交换分区的情况下,并且你那么幸运让唯一索引列包含了分区依据列的话,你完全可以让唯一与表分区对齐,而且不用担心交换分区的影响;
2.      如果不需要进行交换分区的情况下,唯一索引不包含分区依据列,那就让唯一索引单独使用一个文件组,这样性能也能得到一部分的提升;
3.      如果需要进行交换分区的情况下,唯一索引不包含分区依据列,那就让唯一索引单独使用一个文件组,但是你需要在进行交换分区之前:停止TCP/IP防止进数据,重启服务,删除唯一索引,交换分区,创建唯一索引,启用TCP/IP,重启服务;(貌似这不是个好方法,欢迎大家提供好的方案)

六、参考文献


定义了索引视图时的分区切换
使用分区切换高效传输数据
已分区索引的特殊指导原则(唯一索引)
设计分区以管理数据子集

原文链接

SQL Server 当表分区遇上唯一约束(转载)相关推荐

  1. sql加上唯一索引后批量插入_MySQL当批量插入遇上唯一索引

    一.背景 以前使用SQL Server进行表分区的时候就碰到很多关于唯一索引的问题:Step8:SQL Server 当表分区遇上唯一约束,没想到在MySQL的分区中一样会遇到这样的问题:MySQL表 ...

  2. sql加上唯一索引后批量插入_MySQL批量插入遇上唯一索引避免方法

    一.背景 以前使用SQL Server进行表分区的时候就碰到很多关于唯一索引的问题:Step8:SQL Server 当表分区遇上唯一约束,没想到在MySQL的分区中一样会遇到这样的问题:MySQL表 ...

  3. SQL Server 批量主分区备份(One Job)

    原文:SQL Server 批量主分区备份(One Job) 一.本文所涉及的内容(Contents) 本文所涉及的内容(Contents) 背景(Contexts) 案例分析(Case) 实现代码( ...

  4. 利用T-SQL处理SQL Server数据库表中的重复行

    Duplicate rows in a SQL Server database table can become a problem. We will see how we can find and ...

  5. SQL Server 深入解析索引存储(上)

    SQL Server 深入解析索引存储(上) 原文:SQL Server 深入解析索引存储(上) 标签:SQL SERVER/MSSQL SERVER/数据库/DBA/索引体系结构/堆 概述 最近要分 ...

  6. SQL Server 2005利用分区对海量数据的处理 [转自13590--北极燕鸥]

    超大型数据库的大小常常达到数百GB,有时甚至要用TB来计算.而单表的数据量往往会达到上亿的记录,并且记录数会随着时间而增长.这不但影响着数据库的运行效率,也增大数据库的维护难度.除了表的数据量外,对表 ...

  7. SQL SERVER系统表

    系统表查看 SQL SERVER系统表在系统数据库master中,其实确切的说这些系统表是视图,可以在master库下的视图下查看 常用系统表及功能 sysaltfiles 主数据库 保存数据库的文件 ...

  8. SQL Server创建表和添加列

    撰写时间:2022 年 4 月 27日 SQLServer创建表和添加列 SQL Server创建表: 表用于在数据库中存储数据:表在数据库和模式中唯一命名.每个表包含一个或多个列.每列都有一个相关的 ...

  9. columnproperty server sql_导出SQL Server数据库表中字段的说明/备注

    时 间:2013-02-18 09:09:11 作 者:摘 要:导出SQL Server数据库表中字段的说明/备注 正 文: 打开SQL企业管理器 ,找到你要导出用户表字段信息的那个数据库 ,点击工具 ...

最新文章

  1. 信息安全系统设计基础第十一周学习总结
  2. 微信公众号平台开发-网页授权
  3. jQuery $.ajax传递数组的traditional参数传递必须true 对象的序列化
  4. 蓝桥杯C++ AB组辅导课 第二讲 二分与前缀和 Acwing
  5. phpcms 指定id范围 调用_phpcms v9使用GET调用指定id文章内容、页面数据方法
  6. boost::callable_traits的is_lvalue_reference_member的测试程序
  7. thinkphp仿素材火教程_国外都用古风效果图获奖了,为什么你连素材都没有?
  8. dm8148 videoM3 link源代码解析
  9. 个人管理 - Learn More,Study Less!
  10. Vue3加载本地assets图片
  11. 如何“复活”一个人,这里有一份最全的技术路线图谱丨钛媒体深度
  12. linux 中压缩文件夹命令行,Linux 文件夹 压缩 命令
  13. 返利网是如何做到订单跟踪的?
  14. 百度云离线下载含有违规内容检测方法分析
  15. 目标检测 (Detection) 算法综述
  16. java猴子分桃问题_通俗易懂、简单粗暴得解决猴子分桃问题
  17. python解包exe_Pyinstaller打包的EXE之解包
  18. 【评测】TaqMan️探针和IDT PrimeTime️ 双淬灭探针的对比
  19. 【Linux】Linux知识点汇总
  20. html实现点击部分页面跳转,打造营销服务闭环,在基木鱼如何利用美洽高效赋能客户...

热门文章

  1. 置入式模型inclusion model和显示具现化
  2. C++设计模式--观察员
  3. SQL SERVER事务处理
  4. poj1091:跳蚤【容斥原理】
  5. 伟大骡子的一生和性能测试
  6. java自学-基本数据类型
  7. 广搜最短路径变形,(POJ3414)
  8. 自定义委托,事件,参数的简单随笔
  9. 意外发现一个很不错的涂鸦作者
  10. [转]asp.net 动态添加多附件上传