日期:2014-02-02  浏览次数:20619 次

SQL Server 分区视图允许各机构调节各自系统以处理大量数据。这种功能使您能够在多个表之间对数据进行分区;在逻辑上通过视图把各个表联合起来,使分区尽可能对用户与开发人员透明。以前发表的几篇文章(包括我和 Kalen Delaney 发表的两篇,其中一篇“分布式分区视图”2000 年 8 月发表,InstantDoc ID 9086,另一篇“查询分布式分区视图”2000 年 9 月发表,InstantDoc ID 9097)曾经介绍了分区视图。SQL Server 联机丛书 (BOL) 也涉及到一些基础知识。在这篇文章中,我与您分享一些您可能不曾注意到的技巧,包括使用 Enterprise Manager 对分区进行架构更改的负作用,如何绕过对通过分区视图向表中插入数据的方式的限制,以及在分区标准中使用常量所引起的问题。iTbulo .comghNrndK

Enterprise Manager 中更改分区iTbulo .comghNrndK

我极为提倡使用 T-SQL,甚至是对于您通过 Enterprise Manager 能轻易执行的任务。除了可提高 T-SQL 技能,这种方法使我更好地明白我所做的操作并予以更多控制。另外,Enterprise Manager 并不总是以最有效的方式执行任务。例如,从 Enterprise Manager 对分区进行架构更改,会降低分区的性能与功能。为处理这个问题,首先运行清单 1 中的脚本来创建分区 Orders2000、Orders2001 与 Orders2002,以及可更新的分区视图 Orders。iTbulo .comghNrndK

首先,需确保在检索期间 Orders 在可更新性与分区消除方面提供全面的分区功能。分区排除是指 SQL Server 只访问符合查询筛选标准的相关分区。用以下三个定单填充 Orders。因为每个分区承载不同年份的行,所以各定单要放到不同的分区中:iTbulo .comghNrndK

INSERT INTO Orders(orderid, customerid, orderdate)



VALUES(1, 'aaaa', '20000109')



INSERT INTO Orders(orderid, customerid, orderdate)



VALUES(2, 'aaaa', '20010118')



INSERT INTO Orders(orderid, customerid, orderdate)



VALUES(3, 'aaaa', '20020212')



正如在 BOL ???ù?è???????ù?Orders 分区视图满足了可更新性的所有要求,所以 INSERT 语句很成功。现在,为了验证在数据检索期间是否发生了分区排除,将 STATISTICS IO 设置为打开,并且将 Query Analyzer 中 Query 菜单下的 Show Execution Plan 选项设置为打开。注意,通过将这个选项设置为打开,当运行查询时,您请求优化器生成并使用的实际计划。此选项与 Display Estimated Execution Plan 选项(不运行查询,只显示估计计划)形成对比。iTbulo .comghNrndK

为了测试分区排除,对 Orders 发出下面的 SELECT 语句,来只检索 2000 年 1 月份的数据:iTbulo .comghNrndK

SET STATISTICS IO ON



SELECT * FROM Orders



WHERE orderdate >= '20000101'



AND orderdate < '20000201'



注意在 STATISTICS IO 结果中,SQL Server 物理上只访问了 Orders2000;针对其他所有分区的 I/O 数量为 0:iTbulo .comghNrndK

Table 'Orders2002'. Scan count 0, logical reads 0, ...



Table 'Orders2001'. Scan count 0, logical reads 0, ...



Table 'Orders2000'. Scan count 1, logical reads 2, ...



在图形执行计划中,把鼠标指针悬停在三个群集索引搜索运算符处。注意,在黄色详细资料框中,实际执行的只有 Orders2000 分区计划中的分支(执行数目:1);而其他的则没有被执行(执行数目:0)。iTbulo .comghNrndK

现在,假设必须把 customerid 列从 varchar(5) 增大到 varchar(10)。使用 T-SQL 可以编写一个简短、有效的脚本。这是因为 SQL Server 不需要在物理上访问每行以增大 varchar 列,而只是在元数据中表达这个更改,所以这个脚本可以在瞬间运行。运行以下代码执行更改:iTbulo .comghNrndK

ALTER TABLE Orders2000



ALTER COLUMN customerid VARCHAR(10) NOT NULL



ALTER TABLE Orders2001



ALTER COLUMN customerid VARCHAR(10) NOT NULL



ALTER TABLE Orders2002



ALTER COLUMN customerid VARCHAR(10) NOT NULL



运行此脚本后,尝试检索数据,然后重新运行对 Orders 的查询,并像上面所做的操作一样检查 STATISTICS IO 的计划和结果:iTbulo .comghNrndK

SELECT * FROM Orders



WHERE orderdate >= '20000101'



AND orderdate < '20000201'



注意在结果中发生了分区排除。发出的 INSERT 查询也很成功:iTbulo .comghNrndK

INSERT INTO Orders(orderid, customerid, orderdate)



VALUES(4, 'aaaa', '20020828')



要查看 Enterprise Manager 如何处理这个更改,单击 tempdb 数据库(分区在此数据库中创建)下的 Tables 文件夹,然后右击 Orders2000 表,选择 Design Table。在 Design Table 对话框中,把 customerid 列的大小更改为 varchar(15)。对 Orders2001 和 Orders2002 分区重复此过程。在把更改保存到一个分区之前,单击 Save Change Script,并检查 SQL Server 生成的脚本。您应获得 清单 2 对 Orders2002 所示的(简短的)脚本。iTbulo .comghNrndK

Enterprise Manager 更改列大小的效率非常低。首先,它创建了一个新表 Tmp_Orders2002,为 customerid 指定了新的大小。然后,Enterprise Manager 把数据从 Orders2002 中复制到