数据库性能调优是每一个优秀SQL Server管理员最终的责任。虽然保证数据的安全和可用性是我们的最高的目标,但是假如数据库应用程序无法满足用户的要求,那么DBA们会因为性能低下的设计和实现而受到指责。SQL Server 2005在数据库性能方面得到了很多提高,尤其是表分区的技术。如果你还没不了解表分区的特征,那么请你花点时间读这篇文章。
表分区的概念不是一个新的概念;只要你当过一段时间的SQL Server DBA,那么你可能已经对一些频繁访问的表进行过归档,当这个表中的历史数据变的不再经常被访问的时候。比如,假设你有一个打印时间报表的应用,你的报告很少会查询1995年的数据,因为绝大部分的预算规划会基于最近几年的数据。
SQL Server 7和SQL Server 2000支持分布式分区视图(distributed partitioned views,又称为物化视图,materialized views)。分布式分区视图由分布于多台服务器上的、具有相同表结构的表构成,而且你还需要为每一个服务器增加链接服务器定义(linked server definitions),最后在其中一台服务器上创建一个视图将每台服务器上返回的数据合并起来。这里的设计思想是数据库引擎可以利用多台服务器的处理能力来满足查询。
SELECT $PARTITION.TimeEntryDateRangePFN(time_entry_date) AS Partition,COUNT(*) AS [COUNT] FROM fact_time_entry GROUP BY $PARTITION.TimeEntryDateRangePFN(time_entry_date) ORDER BY Partition 表分区对交易环境和数据仓库环境来说,都是一个重要的特征。数据仓库用户最主要的抱怨是移动事实表(fact table)会花费太多时间。当装载数据到事实表的时候,用户查询(立方体处理查询)的性能会明显下降,甚至是完全无法成功。因此,装载大量的数据到事实表的时候常常需要停机。如果使用表分区,就不再出现这样的情况——确切的讲,你一眨眼的工夫就可以移动事实表。为了演示这是如何生效的,我使用上面例子中相同的分区函数和表结构来创建一个新的表,这个表叫做fact_time_entry2。表的主键从五千万开始,这样fact_time_entry2就不会包含表fact_time_entry中已经有的数据。
现在我把2007年的数据移动到这张fact_time_entry2中。同时让我们假设fact_time_entry表中包含着2007年之前的数据。在fact_time_entry2表完成数据的转移,我执行下面的语句: ALTER TABLE fact_time_entry2 SWITCH PARTITION 8 TO fact_time_entry PARTITION 8 这条语句将编号为8的分区,这个分区恰好包含着2007年的数据,从fact_time_entry2移动到了fact_time_entry表中,在我的笔记本电脑上,这个过程只花费了3毫秒。在这短短的3毫秒中,我的事实表就增加了五百万条记录!的确,我需要在交换分区之前,将数据移动到中间表,但是我的用户不需要担心——事实表随时都可以查询!在这幕后,实际上没有数据移动——只是两张表的元数据发生了变化。
我可以使用类似的查询删除事实表中不在需要的数据。例如,假设我们决定我们不再关心2004年的记录。下面的语句可以将这些记录转移到我们创建的工作表中: ALTER TABLE fact_time_entry SWITCH PARTITION 2 TO fact_time_entry2 PARTITION 2 这样的语句依旧在毫秒级内完成了。现在,我可以删除fact_time_entry2或者将它移到其他的服务器上。我的事实表不会包含2004年的任何记录。这个分区还是需要在目的表中存在,而且它必须是空的。你不能将分区转移到一个包含重复数据的表中。源表和目的表的分区必须一致,同时被转移的数据必须在同一个文件组中。即使受到这么多的限制,转换分区和无需停机就可以移动数据表的功能必将让数据仓库的实现变的前所未有的轻松。