在SQL Server中对大型表进行分区的最佳方法是什么?
在最近的项目中,"主要"开发人员设计了一种数据库模式,其中"较大"的表将被拆分成两个单独的数据库,并在主数据库上具有将两个单独的数据库表合并在一起的视图。主数据库是从应用程序中删除的数据库,因此这些表看起来和感觉都像普通表(除了一些有关更新的古怪事物)。这似乎是一个巨大的性能问题。我们确实在这些桌子周围发现了性能问题,但是没有什么可以让他改变对设计的想法。只是想知道什么是最好的方法,或者它是否值得?
解决方案
我们正在使用哪个版本的SQL Server? SQL Server 2005具有分区表,但是在2000(或者7.0)中,我们需要使用分区视图。
另外,将表分区放在单独的数据库中的原因是什么?
在过去(2005年之前)必须对表进行分区时,通常是按日期列或者类似的方式对各个分区进行查看。联机丛书有一个部分讨论如何执行此操作以及围绕它的所有规则。我们需要遵循规则以使其按预期工作。
要记住的关键是分区列必须是主键的一部分,并且我们想尝试在对表的任何访问中始终使用该列,以便优化器可以忽略不应受到查询影响的分区。
在MSDN中查找"分区表",我们应该能够找到有关SQL Server 2005分区表的更完整的教程,以及有关如何设置它们以获得最佳性能的建议。
我不认为通过在单个服务器中的多个数据库之间划分表来真正获得任何收益。我们基本上所做的所有事情都是通过在单个SQL Server实例下拥有多个实例(即在两个不同的DB中打开)来增加使用"表"的开销。
我们有多少个数据集?我有一个客户,在SQL Server中有一个600万行表,其中包含2年的销售数据。他们在交易中使用它并进行报告,而没有任何明显的速度问题。
当然,调整索引并选择正确的聚集索引对于性能至关重要。
如果数据集确实很大,并且我们希望进行分区,那么在物理服务器之间对表进行分区时,我们将获得更多收益。
我们是在询问数据库设计方面的最佳实践,还是说服领导改变主意? :)
在设计方面……早在过去,有时需要垂直分区来解决数据库引擎的限制,即表中的列数是硬限制,例如255列。如今,主要的好处纯粹是提高性能:将很少使用的列或者Blob放在单独的磁盘阵列上。但是,如果我们定期从两个表中提取数据,则可能会造成损失。听起来领导正在遭受过早优化的困扰。
在告诉你领导是错误的方面……这需要外交。如果他意识到表现不满的声音,那么基准测试可能是证明两者之间差异的最好方法。
使用"从view1中选择* *创建表t1"在某处创建一个新的物理表,然后使用垂直分区的表和新表运行一些冗长的批处理。如果它像我们所说的那样糟糕,那么区别应该很明显。
但这也可能是过早的优化。找出最终用户对性能的看法。如果性能足够好(对于良好的定义),请不要修复未损坏的东西。
分区并不是一件容易的事,因为可能会有许多细微的性能影响。
我的第一个问题是要简单地将较大的表对象放在单独的文件组中(在不同的主轴上),还是要在表对象内部进行数据分区?
我怀疑所描述的情况是试图将某些大型表与其他表实际存储在不同的主轴上。在这种情况下,将增加单独数据库的额外开销,失去在所有数据库之间强制执行引用完整性的能力,并且启用跨数据库所有权链接的安全隐患不会比在单个数据库中使用多个文件组带来任何好处。如果我们在问题中引用的单独数据库甚至没有存储在单独的主轴上,而是全部存储在同一主轴上,那么即使我们通过物理上分离磁盘活动和绝对没有任何好处。
我建议我们不要使用其他数据库来容纳大型表,而应该查看SQL Server联机丛书中的"文件组"主题,或者要快速查看该文章,请参阅:http://www.mssqltips.com/tip.asp?tip=1112.
如果我们对数据分区(包括划分成多个文件组)感兴趣,那么我建议阅读Kimberly Tripp的文章,他在SQL Server 2005推出时提供了有关此方面的改进的出色演讲。这份白皮书是一个不错的起点:http://www.sqlskills.com/resources/Whitepapers/Partitioning%20in%20SQL%20Server%202005%20Beta%20II.htm。
我不同意分区无法获得任何收益的假设。
如果分区数据在物理上和逻辑上是对齐的,那么查询的潜在IO应该大大减少。
例如:我们有一个表,其中的批处理字段为INT,代表INT。
如果我们通过该字段对数据进行分区,然后针对特定批次重新运行查询,则应该能够在分区前后将set statistics io ON运行,并看到IO减少,
如果每个分区有一百万行,并且每个分区都写入一个单独的设备。该查询应该能够消除不必要的分区。
我没有在SQL Server上做很多分区,但是我有在Sybase ASE上进行分区的经验,这就是所谓的分区消除。如果有时间,我将在SQL Server 2005计算机上测试该方案。
表分区具有绝对的好处(无论它位于相同或者不同的文件组/磁盘上)。如果正确选择了分区列,我们将意识到查询将仅命中所需的分区。因此,想象一下,如果我们有1亿条记录(我对表进行了分区,远大于约20亿以上的行),并且如果大部分数据访问中的70%以上只是某个类别或者时间轴或者数据类型,那么它有助于将访问量最大的数据保存在单独的分区中。另外,我们可以将分区与具有不同类型磁盘(SATA,光纤通道,SSD)的单独文件组对齐,以便访问/忙碌的数据位于最快的存储上,而访问/最少的数据实际上位于较慢的磁盘上。
尽管在SQL Server中,与Oracle不同,分区能力有限。我们只能选择一列进行分区(即使在sql 2008中也是如此)。因此,我们必须明智地选择一个列,该列也是大多数常见查询的一部分。在大多数情况下,人们发现按日期列选择分区很容易。但是,尽管以这种方式进行分区似乎很合逻辑,但是如果查询中没有该列作为条件的一部分,则我们将无法从分区中获得足够的收益(换句话说,无论如何,查询将遍历所有分区)。
数据仓库/数据挖掘类型数据库的分区比OLTP容易得多,因为大多数DW数据库查询受时间段的限制。
这就是为什么现在由于数据库要处理的数据量大,所以明智的设计应用程序的方式是使查询受到更广泛的组(例如时间,地理位置等)的限制,以便在选择此类列时分区将获得最大的好处。