我有一个关于 SQL Server 2008 表设计的一般性问题。我们目前有一个超过 600GB 的表,并且以每天大约 3GB 的速度增长。该表具有适当的缺陷,但在运行查询时正成为主要的障碍,这仅仅是因为它的大小。问题是我应该按年和月将表拆分为多个表(这将适合其他部门拆分其大型数据集的方式)还是应该利用 SQL Server 中内置的分区。使用分区似乎需要更少的代码更改。根据我在分区时读到的内容,您仍然只是查询一个表,服务器处理如何获取数据。如果我们走多表路线,我们将不得不处理从多个表中提取数据。
“此表有适当的缺陷,但在运行查询时已成为主要问题”
除非 SQL Server 能够在运行查询时消除分区,否则单独分区并不能提高查询性能。您的 WHERE 子句需要与您的分区方式保持一致。我们只有一个字段用作分区字段,因此如果您的 WHERE 子句中不包含该字段,尽管有分区,您仍然可能会扫描整个表。
“而且只是因为它的大小。”
分区可以使某些维护操作更容易,但是我们仍然不能在逐个分区的基础上做一些事情。如果索引维护和统计更新给您带来问题,您最好将设计拆分为存档表和实时更新表。当您需要定期将数据从活动表移动到存档表时,您可以这样做,使用 100% 填充因子重建索引,使用全扫描更新统计信息,然后将其文件组设置为只读。分区可以帮助加载存档表 - 但对活动表进行分区可能不会。(我在这里抛出了几个高级概念,好像它既快速又简单,但我只是在这里勾勒出一些背景。)
“看来使用分区将需要更少的代码更改。”
有点 - 乍一看,它看起来像这样,但你越深入,你就会有分区视图之类的选项。您可以重命名现有表,在其位置放置一个视图,然后您可以对基础表进行自己的更改(并添加多个表),而无需更改您的应用程序。
我在这里写了更多关于分区的陷阱:
http://www.brentozar.com/archive/2008/06/sql-server-partitioning-not-the-answer-to-everything/
单独分区可能就足够了,但结合分区视图和多个表可能会获得更好的结果。这在很大程度上取决于查询和增长的模式。
分区的当前限制是列统计信息仅在表中维护,而不是在分区级别。如果您的查询模式可以从更准确的统计信息中受益,那么将表分区与分区视图相结合可以产生显着的性能优势。
当您的数据的性质因月、年而异时,分区视图也可以提供帮助。想象一个零售商不断地改变其产品线,因此每年使用的 Product.ProductId 范围几乎没有一致性。使用单个 order/orderdetail 表和单个统计直方图,统计信息对查询优化器的作用很小。按月分区并结合分区视图(Order、OrderLine)的每年表(Order_2010、Order_2011、OrderLine_2010、OrderLine_2011)将为优化器提供更精细且可能有用的统计信息。
您可以以相对较少的努力引入表分区,因此从那里开始,衡量影响,然后评估分区视图是否值得额外的努力。
Kimberly Tripp发表了很多关于分区的指导和白皮书,通常被认为是该主题的必读内容。Kendra Little也有一些很好的材料和其他文章的有用参考列表
性能通常是人们寻求分区的第一大原因。就个人而言,我认为恢复时间的改进与 VLDB 具有同等或更大的好处。在开始之前花一些时间了解部分可用性和零碎恢复,因为它可能会影响您采用的方法。
如果您有通过网络发送备份的不理想但并不罕见的过程,您可能会看到当前 600GB 的恢复时间为 3 小时。在您突破 1.5TB 的一年中,您遇到了问题。
正如你所说,你有两个选择:
使用 1,您可以创建一个将所有这些表联合在一起的 VIEW,并且只需更新它以包含新创建的表。我认为这确实是一种模拟分区的方法。此方法的优点包括不需要 SQL Server 企业版。
使用 2,您可以将索引与分区对齐,并将分区与不同的存储对齐。在您设置分区功能和分区方案后,这会在您拆分或合并分区时为您完成。这种方法的优点包括不需要手动将记录移动到新表中。由于分区函数和分区方案会为您处理这个问题。此外,正如您所说,访问数据几乎不需要更改代码。
如果你有企业版,我肯定会看看分区。尽管它看起来很复杂,但实际上并没有那么糟糕。如果没有,分区甚至不是您的选择。
创建分区表
修改分区表
设计分区以管理数据子集
希望这可以帮助,
马特
从您的问题来看,您似乎正在存储历史数据(日志),而您的限制似乎来自查询速度,而不是存储空间问题。对我来说,分区无济于事。
当您说您有适当的索引时,它是否在日期字段中包含索引?我在 trunc(timestamp, day) 和 Postgres 上使用索引取得了很好的效果。然后,您必须确保所有查询都在进行任何其他操作之前进行选择。请注意,带有时区字段的时间戳不可索引(因为它根据时区“移动”),因此您需要一个“固定”时间戳才能被索引。