前言
很多的技术人员总是特别青睐“分区表”,每每谈及分区的时候,很多人都喜欢说这样的话语“表中的数据已经达到了千万级别,要搞分区…”。很多人以为:分区就一定可以提升性能;很多人以为:表中的记录上千万就必须得分区;很多人认为:分区是很好,是个神器,可以搞定很多的问题。
于是很多技术人员就开始搞分区,花了很大的精力和很多的时间做分区。他们没有对分区对数据库的影响和维护成本做评估,也就是说,在分区之前无法肯定分区一定可以带来好处,很多时候都是带着猜测和碰运气的心理,很多人都是听信一些“传说”,最后导致很多的问题。
在我们团队与技术人员交流的流程中,我们也发现很多上述的误解。因为我们AgileSharp团队已经为很多的企业和项目做了数据库优化方面的东西,对分区也有些理解和经验,这里和大家分享一下,希望朋友理智的对待“分区”这个事物。
言归正传,表分区可以使得一个很大的数据表已经其上的索引更加容易进行管理,同时,它也可以适当的提升一些基于条件过滤的查询的性能。我们本系列文章将会讲述分区表的涵盖的各个方面,包括:分区函数与分区方案的设计策略,同时,我们还会讨论分区的删除,分区的并行问题,索引分区的维护等问题。
概述
当一个数据表中的数据不断的增长,到里面的数据的大小达到了上百GB甚至更大的时候,加载新数据,删除旧的数据,维护索引会变得更加困难。先不谈其他的因素的影响,就当单纯就表的大小而已,就会使得上述操作花费更多的时间。SQL Server引入表分区来试图解决上述问题,从而使得数据更好的被管理。
分区的概念其实是很容易理解的,就是把一个大的表进行拆分,把表中的数据和索引分布到很多不同的分区中,从而使得一些数据维护操作变得更加在每个分区上面进行,而不是总是在整表上面进行。其实这就有点分而治之的意思。除此之外,SQL Server的优化器可以更加查询选择合适的分区,这样在一定程度上面提示了性能。
接下来的文章涵盖了使用在SQL Server 2005(以及以后的版本)中的分区表和索引的策略和最佳实践。其目的是为数据仓库和OLTP系统的数据库架构师,开发人员和管理员提供从中级到高级的参考材料。
为什么要分区
什么是分区?为什么要使用分区?简单的回答是:为了改善大型表以及具有各种访问模式的表的可伸缩性和可管理性。通常,创建表是为了存储某种实体(例如客户或销售)的信息,并且每个表只具有描述该实体的属性。一个表对应一个实体是最容易设计和理解的,因此不需要优化这种表的性能、可伸缩性和可管理性,尤其是在表变大的情况下。
大型表是由什么构成的呢?超大型数据库 (VLDB) 的大小以数百 GB 计算,甚至以 TB 计算,但这个术语不一定能够反映数据库中各个表的大小。大型数据库是指无法按照预期方式运行的数据库,或者运行成本或维护成本超出预定维护要求或预算要求的数据库。这些要求也适用于表;如果其他用户的活动或维护操作限制了数据的可用性,则可以认为表非常大。
例如,如果性能严重下降,或者每天、每周甚至每个月的维护期间有两个小时无法访问数据,则可以认为销售表非常大。有些情况下,周期性的停机时间是可以接受的,但是通过更好的设计和分区实现,通常可以避免或最大程度地减少这种情况的发生。虽然术语 VLDB 仅适用于数据库,但对分区来说,了解表的大小更重要。
除了大小之外,当表中的不同行集拥有不同的使用模式时,具有不同访问模式的表也可能会影响性能和可用性。尽管使用模式并不总是在变化(这也不是进行分区的必要条件),但在使用模式发生变化时,通过分区可以进一步改善管理、性能和可用性。还以销售表为例,当前月份的数据可能是可读写的,但以往月份的数据(通常占表数据的大部分)是只读的。在数据使用发生变化的类似情况下,或在维护成本随着在表中读写数据的次数增加而变得异常庞大的情况下,表响应用户请求的能力可能会受到影响。相应地,这也限制了服务器的可用性和可伸缩性。
此外,如果以不同的方式使用大量数据集,则需要经常对静态数据执行维护操作。这可能会造成代价高昂的影响,例如性能问题、阻塞问题、备份(空间、时间和运营成本),还可能会对服务器的整体可伸缩性产生负面影响。
分区可以带来什么帮助?
当表和索引变得非常大时,分区可以将数据分为更小、更容易管理的部分,从而提供一定的帮助。本文重点介绍横向分区,在横向分区中,大量的行组存储在多个相互独立的分区中。分区集的定义根据需要进行自定义、定义和管理。Microsoft SQL Server 2005 允许您根据特定的数据使用模式,使用定义的范围或列表对表进行分区。SQL Server 2005 还围绕新的表和索引结构设计了几种新功能,为分区表和索引的长期管理提供了大量的选项。
此外,如果具有多个 CPU 的系统中存在一个大型表,则对该表进行分区可以通过并行操作获得更好的性能。通过对各个并行子集执行多项操作,可以改善在极大型数据集(例如数百万行)中执行大规模操作的性能。通过分区改善性能的例子可以从以前版本中的聚集看出。例如,除了聚集成一个大型表外,SQL Server 还可以分别处理各个分区,然后将各个分区的聚集结果再聚集起来。
在 SQL Server 2005 中,连接大型数据集的查询可以通过分区直接受益;SQL Server 2000 支持对子集进行并行连接操作,但需要动态创建子集。在 SQL Server 2005 中,已分区为相同分区键和相同分区函数的相关表(如 Order 和 OrderDetails
表分区
在SQL Server中,对于分区有两种方式,一种是表外分区,另外一种就是表内分区。我们把一个大的数据表中的数据拆分到很多的不同的结构相同的物理表中,这就是所谓的“表外分区”;同时,我们还可以把一个大的表就在表内进行分区,我们常常谈到的表分区就是这个概念。
一般而言,有两个主要的方法可以把一个表中的数据拆分到多个表中:
1.这个方法也称之为水平拆分,就是选择表中一部分数据,然后将之放在其他的表中。这个时候就要考虑是查询和数据操作如何在这些拆分后的表上面进行。此时,如果去修改程序肯定会造成很大的影响,为了表的拆分对程序那边保持透明,我们必须在这些表上面去建立一个视图,所有的数据操作都在这个视图上面进行,这就是所谓的“分区视图”。在分区视图中,我们必须手动应用所需的一些数据的约束,并且维护也将变得复杂和费时。
2.第二种方法就是所谓的“垂直拆分”。主要基于表中的列进行拆分,如果表中有20列,如A-T,我们根据相关的业务和数据的使用,我们把A-H拆分到一个单独的表中,把I-M拆分到另外一个表中,N-T拆分到一个表中。这里需要注意的就是:拆分后面的每个表中的数据的条数是一样的,只是列不同,并且每个表中主键都是一样的,这主要是为了确保后续数据操作的方便。一般而言,我们还是会在这些表上面去建立一个视图,从而使得程序那边依然保持不变。在SQL Server中,没有提供内在的垂直拆分的机制,如果要实现,就需要我们自己规划。
SQL Server的表分区不同于上述两种方法,因为它主要是由一个单一的表进行分区,不参与多个物理表。当表被创建为一个分区表时,SQL Server会自动将正确的数据行放在不同的分区表中,SQL Server维护幕后的分区和一切操作。我们可以执行单独的分区维护操作,并可以使得过滤查询只能访问正确的分区。