《Microsoft Sql server 2008 Internals》读书笔记--第八章The Query Optimizer(8)
《Microsoft Sql server 2008 Internals》读书笔记订阅地址:
http://www.cnblogs.com/downmoon/category/230397.html/rss
《Microsoft Sql server 2008 Internals》索引目录:
《Microsoft Sql server 2008 Internal》读书笔记--目录索引
本文继续了解索引视图(Indexes View)
关于索引视图的基本概念,可以在MSDN了解:http://msdn.microsoft.com/zh-cn/library/ms188783.aspx
注意:虽然索引视图是在SQL Server 2000中已经加入,但只有SQL Serer 2008的企业版才支持索引视图的匹配。
我们看一个例子:
Create table Table2(id int primary key identity,commentid int ,product nvarchar(200));
insert into Table1(id,submitdate,commment) values(1,'2008-01-09','downmoon index view')
insert into Table2
select 1,'SQL Server 2008 r2'
Create view dbo.v1 with schemabinding
as
select t1.id,t1.submitdate,t1.commment,t2.product from dbo.Table1 t1
inner join dbo.Table2 t2 on t1.id=t2.commentid
go
Create unique clustered index idx1 on v1(id);
对于以下三种查询:
以上三种查询的成本其实是一样的,因为在索引视图的匹配得到了相同的结果。
查询优化器并非匹配所有的视图,我们看一个不匹配的例子:
Insert into table3
select 10
union all select 20
union all select 30
Create view dbo.v2 with schemabinding
as
select t3.col1,t3.col2 From dbo.table3 t3 where t3.col2>20;
go
Create unique clustered index idx2 on v2(col1);
select * from dbo.v2 where col2=CONVERT(int,10);
对于不匹配的索引视图,SQL Server直接在基表而不在视图中查询。
其实这是个0行查询,因为 col2=10 and col2>20这个条件,SQL Server查询优化器根本不会执行。
SQL Server也支持匹配在某些案例下的索引视图,如列和行的子集。
Create unique clustered index idx3 on basetbl1(col1);
set nocount on
BEGIN TransAction;
Declare @i int
set @i=0
while @i<50000
BEGIN
Insert into basetbl1(col1,col2) values(@i,50000-@i);
set @i=@i+1
END
Commit Transaction
go
create view dbo.v3 with schemabinding
as
select col1,col2 From dbo.basetbl1 t3
go
create unique clustered index iv3 on dbo.v3(col2);
而如果有列的计算,则会添加计算纯量(Scalar)
别担心,SQL Server在一整套的索引视图支持结构中设置了一些限制,以确保视图能够在适当的时候被创建、匹配、尽可能高效地被更新。
■分区表
当SQL Server的被用于存储越来越多的数据时,大数据库的管理成为DBA们的恶梦。 首先,执行操作(如索引重建等)的时间与数据大小一起增长,甚至会影响系统的可用性。其次,大表的大小使得执行操作变得困难了,因为系统可用的资源(如临时空间、日志空间和物理内存等)是有限的。此时,表和索引分区将会帮你更好地管理大数据库,并使宕机的可能性最低。
关于SQL Server 2008的表分区的界面操作,陈希章有一篇文章,
使用SQL Server 2008提供的表分区向导
另外,MSDN:
http://msdn.microsoft.com/zh-cn/library/ms179854.aspx
http://technet.microsoft.com/zh-cn/library/ms345599.aspx
物理上,分区表和索引其实是存储了行的分数(或分量fraction)的N个表或索引,当这些与他们的非分区的等值相比较时,计划的差异通常是分区案例被请求遍历表或索引的列表以返回所有的行。在SQL Server 2005中,这通过APPLY操作符表示,本质上就是一个嵌套循环连接。在SQL Server 2005表示中,一个分区IDs的特殊表被通过参数传递到一个(遍历每个分区的)连接内部的查询执行组件。这个机制在大多数情况下工作得很好,但在某些重要的场景,这个模型却不适合。例如,在请求的并行查询计划里有一个限制(restriction),即并行表或索引scan内容(多个线程同时从一个表读取行以改善性能)时,不能工作在嵌套内循环连接的内侧,而这在SQL Server 2005装箱前是不可能被修复的。不幸的是,这是SQL Server 2005中表分区的主要案例。而且,APPLY表示选项启用连接协作,即以同一种方式分区的两个表能被高效地连接。这种设计初衷本来很好,但在实际中并不能实现最初所预想的那样。正是因为这个,SQL Server 2008重新定义了分区表的表示。
SQL Server 2008在大多数情况下通过(与访问分区表或索引的操作符一起)存储分区来表示分区。这可以带来一些改进,比如可以使并行scan能正常地工作。它也移去了一些在查询优化器中的分区或非分区案例之间的差异,这将避免错过最佳的性能优化机会。
我们看一个例子:
Create partition scheme ps2008 as partition pf2008 all to ([PRIMARY])
Create table ptnsales(saledate date,salesperson int,amount money) on ps2008(saledate);
insert into ptnsales
select '2008-10-20',1,250.00
union all select '2008-11-05',2,129.00
union all select '2008-12-23',2,98.00
union all select '2008-10-3',1,450.00
此模型的一个好处是可以跨分区表进行并行查询:
Create partition scheme psparallel as partition pfparallel all to ([PRIMARY])
go
create table testscan(randomnum int,value int,data binary(3000)) on psparallel(randomnum)
go
set nocount on
BEGIN TransAction;
Declare @i int
set @i=0
while @i<100000
BEGIN
Insert into testscan(randomnum,value) values(rand()*400,@i);
set @i=@i+1
END
Commit Transaction
分区表未完待续。
下文将关注分区表(Partitioned Tables) 和数据仓库(Data Warehousing)