SQL Server 2005 分区表实践

SQL Server 
2005
 分区表实践——建立分区表(partition 
table
) 
问题:有一个订单表 Orders,要转换成分区表,以订单日期 OrderDate 为分区列,目前含有订单日期为 
1996
-
07
-
04
 
~
 
1998
-
05
-
06
 的数据。可以在 SQL Server 
2000
 Northwind 数据库中找到 Orders 表,下面是简化了的表结构: 


create
 
table
 dbo.Orders
(
   OrderID     
int
          
not
 
null

  ,CustomerID  
varchar
(
10
)  
not
 
null

  ,EmployeeID  
int
          
not
 
null

  ,OrderDate   
datetime
     
not
 
null

  
  ,
constraint
 PK_Orders 
primary
 
key
 noclustered (OrderID, CustomerID)
)

go



create
 
clustered
 
index
 IXC_Orders_OrderDate 
on
 dbo.Orders(OrderDate)

go



1
. 创建分区函数(partition 
function
) 
在创建分区函数的时候,我一般这样命名分区函数:
'
PF
'
 
+
 
Table
 Name 
+
 分区字段名 
+
 
'
Range
'
,例如:
'
PF_Orders_OrderDateRange
'
,如果字段名较长的话,则可以省略去,可以这样命名: 
'
PF_Orders_DateRange
'
 


create
 partition 
function
 PF_Orders_OrderDateRange(
datetime
)

as

range 
right
 
for
 
values
 (

'
1997-01-01
'
,

'
1998-01-01
'
,

'
1999-01-01
'

)

go


分区函数 
'
PF_Orders_OrderDateRange
'

3
 个边界值(
'
1997-01-01
'
, 
'
1998-01-01
'
, 
'
1999-01-01
'
),这三个边界值(boundary value)组成了 
4
 个分区(partition),并且 “range 
right
” 表明边界值属于右边的分区。下面使用存储过程 dbo.sp_show_partition_range 来查看分区范围: 


exec
 dbo.sp_show_partition_range 
@partition_function
 
=
 
'
PF_Orders_OrderDateRange
'


partition_function        partition   minval                    value     maxval

--
----------------------- ----------- ------------------------- --------  ------------------------


PF_Orders_OrderDateRange  
1
           
NULL
                      
<=
 val 
<
  
1997
-
01
-
01
 
00
:
00
:
00.000

PF_Orders_OrderDateRange  
2
           
1997
-
01
-
01
 
00
:
00
:
00.000
   
<=
 val 
<
  
1998
-
01
-
01
 
00
:
00
:
00.000

PF_Orders_OrderDateRange  
3
           
1998
-
01
-
01
 
00
:
00
:
00.000
   
<=
 val 
<
  
1999
-
01
-
01
 
00
:
00
:
00.000

PF_Orders_OrderDateRange  
4
           
1999
-
01
-
01
 
00
:
00
:
00.000
   
<=
 val 
<
  
NULL


每个分区的最大值和最小值,一清二楚。获得 dbo.sp_show_partition_range 代码。 


2
. 创建分区方案(partition scheme) 
分区方案定义了,分区表或者分区索引的每个分区的数据存放在哪个文件组上。试想,如果没有分区方案的话,如何实现把分区表中不同的分区存放在不同的文件组上?我们可以看下创建普通数据表的语法: 


create
 
table
 
[
table name
]
 ... 
on
 
[
filegroup
]


显然,普通表整个表的数据,只能存放在同一个文件组上。为了实现分区机制,才引入了分区方案这个概念。每个分区表只属于一个方案(scheme),因此分区方案可以这样命名:
'
PS
'
 
+
 
Table
 Name 


create
 partition scheme PS_Orders

as

partition PF_Orders_OrderDateRange

to
 (
[
primary
]
, 
[
primary
]
, 
[
primary
]
, 
[
primary
]
)

go


分区方案 PS_Orders 规定了,把分区表的 
4
 个分区分别存放在主文件组 
primary
 上。分区方案中指定的文件组数目,不能少于分区函数中划定的分区数目;但可以多于分区函数中划定的分区数目。多出的第 
1
 个文件组用来指定当分区表增加分区时,下一个分区所使用的文件组;多出的其他文件组将被忽略。 

下面的例子,分区方案指定了 
5
 个文件组(多出了 
1
 个文件组)。 


drop
 partition scheme PS_Orders

go



create
 partition scheme PS_Orders

as

partition PF_Orders_OrderDateRange

to
 (
[
primary
]
, 
[
primary
]
,
[
primary
]
, 
[
primary
]
,
[
primary
]
)

go


Partition scheme 
'
PS_Orders
'
 has been created successfully.

'
PRIMARY
'
 
is
 marked 
as
 the 
next
 used filegroup 
in
 partition scheme 
'
PS_Orders
'
.

下面的例子,分区方案指定了 
7
 个文件组(多出了 
3
 个文件组)。 


drop
 partition scheme PS_Orders

go



create
 partition scheme PS_Orders

as

partition PF_Orders_OrderDateRange

to
 (
[
primary
]
, 
[
primary
]
,
[
primary
]
, 
[
primary
]
,
[
primary
]
,
[
primary
]
,
[
primary
]
)

go


Partition scheme 
'
PS_Orders
'
 has been created successfully.

'
PRIMARY
'
 
is
 marked 
as
 the 
next
 used filegroup 
in
 partition scheme 
'
PS_Orders
'
.

2
 filegroup specified after the 
next
 used filegroup are ignored.

如果分区表所有的分区都将分配在同一个文件组 
[
primary
]
 上,那么可以使用下面更简洁的方法: 


drop
 partition scheme PS_Orders

go



create
 partition scheme PS_Orders

as

partition PF_Orders_OrderDateRange

all
 
to
 (
[
primary
]
)

go



3
. 创建分区表(partition 
table
) 
创建了分区函数和分区方案,准备工作做完了,现在终于可以开始创建分区表了。创建分区表和普通表的语法大致相同,不同之处:普通表需要指定所存放的文件组,分区表需要指定分区方案。 


create
 
table
 dbo.Orders
(
   OrderID     
int
          
not
 
null

  ,CustomerID  
varchar
(
10
)  
not
 
null

  ,EmployeeID  
int
          
not
 
null

  ,OrderDate   
datetime
     
not
 
null

)

on
 PS_Orders(OrderDate)

go


根据订单表 Orders 查询时经常使用 OrderDate 范围条件来查询的特点,我们最好在 Orders.OrderDate 列上建立聚集索引(
clustered
 
index
)。为了便于进行分区切换(partition swtich),大多数情况下,建议在分区表上建立分区索引。下面建立聚集分区索引: 


create
 
clustered
 
index
 IXC_Orders_OrderDate 
on
 dbo.Orders(OrderDate)

on
 PS_Orders(OrderDate)

如果没有指定 “
on
 PS_Orders(OrderDate)”,默认建立的聚集索引和分区表的分区方案相同。 

另外 Orders 分区表需要在(OrderID, CustomerID)上建立主键。我们知道主键实际上是个唯一索引,但分区表在建立唯一索引(分区索引)的时候,分区列必须是唯一索引的一部分。为什么要这样子呢?因为 SQL Server 不但要保证索引在各个分区是唯一的,还要保证在整个表中是唯一的。 


alter
 
table
 dbo.Orders 
add
 
constraint
 PK_Orders 
primary
 
key
 (OrderID, CustomerID, OrderDate)

如果不指定 OrderDate 的话,则会出现错误:
1908
 

Msg 
1908
, 
Level
 
16
, State 
1
, Line 
1


Column
 
'
OrderDate
'
 
is
 partitioning 
column
 
of
 the 
index
 
'
PK_Orders
'
.
Partition columns 
for
 a 
unique
 
index
 must be a subset 
of
 the 
index
 
key
.

Msg 
1750
, 
Level
 
16
, State 
0
, Line 
1

Could 
not
 
create
 
constraint
. See previous errors.

查看分区表 Orders 上的索引: 


exec
 sp_helpindex 
'
dbo.Orders
'


index_name            index_description                                      index_keys

--
------------------- ------------------------------------------------------ ------------------------------


IXC_Orders_OrderDate  
clustered
 located 
on
 PS_Orders                         OrderDate
PK_Orders             
nonclustered
, 
unique
, 
primary
 
key
 located 
on
 PS_Orders OrderID, CustomerID, OrderDate


4
. 向分区表中填充数据 

insert
 
into
 dbo.Orders

select
 OrderID, CustomerID, EmployeeID, OrderDate
  
from
 dbo.Orders_From_SQL2000_Northwind

数据表 dbo.Orders_From_SQL2000_Northwind,是从 SQL Server 
2000
 中 Northwind.Orders 迁移过来的。 


5
. 查看分区表各分区数据情况(数据行数,最大最小 OrderDate 值) 

select
 partition 
=
 $partition.PF_Orders_OrderDateRange(OrderDate)
      ,rows      
=
 
count
(
*
)
      ,minval    
=
 
min
(OrderDate)
      ,maxval    
=
 
max
(OrderDate)
  
from
 dbo.Orders
 
group
 
by
 $partition.PF_Orders_OrderDateRange(OrderDate)
 
order
 
by
 partition

partition   rows        minval                  maxval

--
--------- ----------- ----------------------- -----------------------


1
           
152
         
1996
-
07
-
04
 
00
:
00
:
00.000
 
1996
-
12
-
31
 
00
:
00
:
00.000


2
           
408
         
1997
-
01
-
01
 
00
:
00
:
00.000
 
1997
-
12
-
31
 
00
:
00
:
00.000


3
           
270
         
1998
-
01
-
01
 
00
:
00
:
00.000
 
1998
-
05
-
06
 
00
:
00
:
00.000


(
3
 row(s) affected)

从以上结果集中可以看出:分区表 Orders 的 
3
 个分区中已经填入了数据。这里要注意 $partition.partition_function_name(expression) 这个函数,或许像我一样:一辈子没见过这样的函数:) 

 

本文由 www.sqlstudy.com 原创,版权所有,转载请注明作者和出处!

本文链接:http:
//
www.sqlstudy.com
/
sql_article.php?id
=
2008071101



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值