Sql Server 2005 怎样建立分区表

对数据库进行评估后,需要对大表进行分区,由以下步骤可完成整个分区过程。
程序代码 程序代码

/*
建立分区表的步骤:
1.建立数据库;
2.新增文件组;
3.为文件组新增文件;
4.建立分区函数;
5.建立分区架构(Scheme);
6.新增表格(引用分区架构)。
*/

USE [MASTER]
GO

-- STEP1:建立数据库
IF EXISTS (Select * FROM [master].[dbo].[sysdatabases] Where [name] = 'TestDemo')
    Drop DATABASE [TestDemo]
GO

Create DATABASE [TestDemo] ON PRIMARY
(
    NAME = N'TestDemo', FILENAME = N'F:\TestDataBase\Data\TestDemo.mdf', SIZE = 3072KB, MAXSIZE = UNLIMITED, FILEGROWTH = 1024KB
)
LOG ON
(
    NAME = N'TestDemo_log', FILENAME = N'F:\TestDataBase\Data\TestDemo_log.ldf', SIZE = 1024KB, MAXSIZE = 2048GB, FILEGROWTH = 10%
)
GO

USE [TestDemo]
GO

-- STEP2:增加文件组
Alter DATABASE [TestDemo] ADD FILEGROUP MASTERFG1
GO

Alter DATABASE [TestDemo] ADD FILEGROUP MASTERFG2
GO

Alter DATABASE [TestDemo] ADD FILEGROUP MASTERFG3
GO

Alter DATABASE [TestDemo] ADD FILEGROUP MASTERFG4
GO

-- STEP3:新增文件并与文件组关联
Alter DATABASE [TestDemo] ADD FILE (NAME = N'MASTERF1', FILENAME = N'F:\TestDataBase\FileGroup\MASTERF1.NDF') TO FILEGROUP MASTERFG1
GO

Alter DATABASE [TestDemo] ADD FILE (NAME = N'MASTERF2', FILENAME = N'F:\TestDataBase\FileGroup\MASTERF2.NDF') TO FILEGROUP MASTERFG2
GO

Alter DATABASE [TestDemo] ADD FILE (NAME = N'MASTERF3', FILENAME = N'F:\TestDataBase\FileGroup\MASTERF3.NDF') TO FILEGROUP MASTERFG3
GO

Alter DATABASE [TestDemo] ADD FILE (NAME = N'MASTERF4', FILENAME = N'F:\TestDataBase\FileGroup\MASTERF4.NDF') TO FILEGROUP MASTERFG4
GO

-- STEP4:建立分区函数
IF EXISTS(Select * FROM [sys].[partition_functions] Where [name] = N'MyPF1')
    Drop PARTITION FUNCTION MyPF1
GO

Create PARTITION FUNCTION MyPF1(BIGINT)
AS RANGE RIGHT
FOR VALUES (N'100000', N'200000', N'300000')
GO

-- STEP5:建立分区架构
If EXISTS(Select * FROM [sys].[partition_schemes] Where [name] = N'MyPS1')
    Drop PARTITION SCHEME MyPS1
GO

Create PARTITION SCHEME MyPS1
AS PARTITION MyPF1
TO (MASTERFG1, MASTERFG2, MASTERFG3, MASTERFG4)
GO

-- STEP6:根据分区架构新建表格
IF EXISTS (Select * FROM [dbo].[sysobjects] Where [ID] = OBJECT_ID(N'[dbo].[TestMaster]') AND OBJECTPROPERTY([id], N'IsUserTable') = 1)
   Drop TABLE [dbo].[TestMaster]
GO

Create TABLE [dbo].[TestMaster]
(
    [AutoId] BIGINT IDENTITY(1,1) NOT NULL,
    [Text] VARCHAR (MAX) NULL CONSTRAINT [DF_TestMaster_Text] DEFAULT (N'有些程序员在撰写数据库应用程序时,常专注于 OOP 及各种 framework 的使用,却忽略了基本的 SQL 语句及其「性能 (performance) 优化」问题。版工曾听过台湾某半导体大厂的新进程序员,所组出来的一段 PL/SQL 跑了好几分钟还跑不完;想当然尔,即使他的 AJAX 及 ooxx 框架用得再漂亮,系统性能也会让使用者无法忍受。以下是版工整理出的一些数据库规划、SQL performance tuning 简单心得,让长年钻研 .NET、AJAX、一堆高深 ooxx framework,却无暇研究 SQL statement 的程序员,透过最短时间对本帖的阅读,能避免踩到一些 SQL 的性能地雷。(注:本帖的 SQL 语句皆经过测试可正常执行无误。有兴趣实验者,可直接拷贝后,粘贴至 SQL Server 中执行。)1、数据库设计与规划 • Primary Key 字段的长度尽量小,能用 small integer 就不要用 integer。例如员工数据表,若能用员工编号当主键,就不要用身分证号码。• 一般字段亦同。若该数据表要存放的数据不会超过 3 万笔,用 small integer 即可,不必用 integer。• 文字字段若长度固定,如:身分证号码,就不要用 varchar 或 nvarchar,应该用 char 或 nchar。• 文字字段若长度不固定,如:地址,则该用 varchar 或 nvarchar。除了可节省存储空间外,存取硬盘时也会较有效率。• 设计字段时,若其值可有可无,最好也给一个默认值,并设成「不允许 NULL」(一般字段默认为「允许 NULL」)。因为 SQL Server 在存放和查询有 NULL 的数据表时,会花费额外的运算动作 [2]。• 若一个数据表的字段过多,应垂直切割成两个以上的数据表,并可用同名的 Primary Key 一对多连结起来,如:Northwind 的 orders、Order Details 数据表。以避免在存取数据时,以「集簇索引 (clustered index)」扫描时会加载过多的数据,或修改数据时造成互相锁定或锁定过久。------------------------------2、适当地建立索引• 记得自行帮 Foreign Key 字段建立索引,即使是很少被 JOIN 的数据表亦然。• 替常被查询或排序的字段建立索引,如:常被当作 Where 子句条件的字段。• 用来建立索引的字段,长度不宜过长,不要用超过 20 个 Byte 的字段,如:地址。• 不要替内容重复性高的字段建立索引,如:性别;反之,若重复性低的字段则适合建立索引,如:姓名。• 不要替使用率低的字段建立索引,以免浪费硬盘空间。• 不宜替过多字段建立索引,否则反而会影响到「Insert、Update、Delete」的性能,尤其是以「OLTP (联机事务处理;在线交易)」为主的网站数据库。• 若数据表存放的数据很少,就不必刻意建立索引。否则可能数据库沿着存放索引的「树状结构」(Balanced Tree) 去搜寻索引中的数据,反而比扫描整个数据表还慢。• 若查询时符合条件的数据很多,则透过「非集簇索引 (non-clustered index)」搜寻的性能,反而 可能不如整个数据表逐笔扫描。• 建立「集簇索引」的字段选择至为重要,会影响到整个索引结构的性能。要用来建立「集簇索引」的字段,务必选择「整数」类型 (键值会较小)、唯一、不可为 NULL。'),
    [StartTime] DATETIME NULL CONSTRAINT [DF_TestMaster_StartTime] DEFAULT (GETDATE()),
    CONSTRAINT [PK_TestMaster] PRIMARY KEY CLUSTERED
    (
        [AutoId]
    ) ON MyPS1([AutoId])
)
ON MyPS1([AutoId]) -- 此处特别注意,不是 PRIMARY。
GO

IF EXISTS (Select * FROM [dbo].[sysobjects] Where [ID] = OBJECT_ID(N'[dbo].[TestMasterB]') AND OBJECTPROPERTY([id], N'IsUserTable') = 1)
   Drop TABLE [dbo].[TestMasterB]
GO

Create TABLE [dbo].[TestMasterB]
(
    [AutoId] BIGINT IDENTITY(1,1) NOT NULL,
    [Text] NVARCHAR (4000) NULL CONSTRAINT [DF_TestMasterB_Text] DEFAULT (N'有些程序员在撰写数据库应用程序时,常专注于 OOP 及各种 framework 的使用,却忽略了基本的 SQL 语句及其「性能 (performance) 优化」问题。版工曾听过台湾某半导体大厂的新进程序员,所组出来的一段 PL/SQL 跑了好几分钟还跑不完;想当然尔,即使他的 AJAX 及 ooxx 框架用得再漂亮,系统性能也会让使用者无法忍受。以下是版工整理出的一些数据库规划、SQL performance tuning 简单心得,让长年钻研 .NET、AJAX、一堆高深 ooxx framework,却无暇研究 SQL statement 的程序员,透过最短时间对本帖的阅读,能避免踩到一些 SQL 的性能地雷。(注:本帖的 SQL 语句皆经过测试可正常执行无误。有兴趣实验者,可直接拷贝后,粘贴至 SQL Server 中执行。)1、数据库设计与规划 • Primary Key 字段的长度尽量小,能用 small integer 就不要用 integer。例如员工数据表,若能用员工编号当主键,就不要用身分证号码。• 一般字段亦同。若该数据表要存放的数据不会超过 3 万笔,用 small integer 即可,不必用 integer。• 文字字段若长度固定,如:身分证号码,就不要用 varchar 或 nvarchar,应该用 char 或 nchar。• 文字字段若长度不固定,如:地址,则该用 varchar 或 nvarchar。除了可节省存储空间外,存取硬盘时也会较有效率。• 设计字段时,若其值可有可无,最好也给一个默认值,并设成「不允许 NULL」(一般字段默认为「允许 NULL」)。因为 SQL Server 在存放和查询有 NULL 的数据表时,会花费额外的运算动作 [2]。• 若一个数据表的字段过多,应垂直切割成两个以上的数据表,并可用同名的 Primary Key 一对多连结起来,如:Northwind 的 orders、Order Details 数据表。以避免在存取数据时,以「集簇索引 (clustered index)」扫描时会加载过多的数据,或修改数据时造成互相锁定或锁定过久。------------------------------2、适当地建立索引• 记得自行帮 Foreign Key 字段建立索引,即使是很少被 JOIN 的数据表亦然。• 替常被查询或排序的字段建立索引,如:常被当作 Where 子句条件的字段。• 用来建立索引的字段,长度不宜过长,不要用超过 20 个 Byte 的字段,如:地址。• 不要替内容重复性高的字段建立索引,如:性别;反之,若重复性低的字段则适合建立索引,如:姓名。• 不要替使用率低的字段建立索引,以免浪费硬盘空间。• 不宜替过多字段建立索引,否则反而会影响到「Insert、Update、Delete」的性能,尤其是以「OLTP (联机事务处理;在线交易)」为主的网站数据库。• 若数据表存放的数据很少,就不必刻意建立索引。否则可能数据库沿着存放索引的「树状结构」(Balanced Tree) 去搜寻索引中的数据,反而比扫描整个数据表还慢。• 若查询时符合条件的数据很多,则透过「非集簇索引 (non-clustered index)」搜寻的性能,反而 可能不如整个数据表逐笔扫描。• 建立「集簇索引」的字段选择至为重要,会影响到整个索引结构的性能。要用来建立「集簇索引」的字段,务必选择「整数」类型 (键值会较小)、唯一、不可为 NULL。'),
    [StartTime] DATETIME NULL CONSTRAINT [DF_TestMasterB_StartTime] DEFAULT (GETDATE()),
    CONSTRAINT [PK_TestMasterB] PRIMARY KEY CLUSTERED
    (
        [AutoId]
    ) ON [PRIMARY]
)
ON [PRIMARY]
GO

-- STEP7:往数据库中新增数据,查看数据库属性,可看到 PRIMARY 大小不变,而 FILEGROUP 文件增大。
DECLARE @Index INT

SET @Index = 0

WHILE @Index < 400000
BEGIN
    SET @Index = @Index + 1
    
    Insert INTO [dbo].[TestMaster] ([StartTime]) VALUES (GETDATE())
    
    Insert INTO [dbo].[TestMasterb] ([StartTime]) VALUES (GETDATE())
END
GO

-- STEP7:创建分页查询采用分区表的数据库表存储过程
IF EXISTS (Select * FROM [dbo].[sysobjects] Where [id] = OBJECT_ID(N'[dbo].[Test_GetTestMaster]') AND OBJECTPROPERTY([id], N'IsProcedure') = 1)
    Drop PROCEDURE [dbo].[Test_GetTestMaster]
GO

Create PROCEDURE [dbo].[Test_GetTestMaster]
@PageSize INT,
@PageIndex INT
AS
BEGIN
    SET NOCOUNT ON;

    Select * FROM (
        Select ROW_NUMBER() OVER (ORDER BY [AutoId] DESC) AS [Row], [AutoId], [Text], [StartTime]
        FROM [TestMaster]
    ) AS TEMP Where [Row]
    BETWEEN ((@PageIndex - 1) * @PageSize + 1) AND (@PageIndex * @PageSize)
END
GO

-- STEP8:创建分页查询没有采用分区表的数据库表过程
IF EXISTS (Select * FROM [dbo].[sysobjects] Where [id] = OBJECT_ID(N'[dbo].[Test_GetTestMasterB]') AND OBJECTPROPERTY([id], N'IsProcedure') = 1)
    Drop PROCEDURE [dbo].[Test_GetTestMasterB]
GO

Create PROCEDURE [dbo].[Test_GetTestMasterB]
@PageSize INT,
@PageIndex INT
AS
BEGIN
    SET NOCOUNT ON;

    Select * FROM (
        Select ROW_NUMBER() OVER (ORDER BY [AutoId] DESC) AS [Row], [AutoId], [Text], [StartTime]
        FROM [TestMasterB]
    ) AS TEMP Where [Row]
    BETWEEN ((@PageIndex - 1) * @PageSize + 1) AND (@PageIndex * @PageSize)
END
GO

-- STEP9:执行采用分区表的数据库表过程
EXEC [dbo].[Test_GetTestMaster] 10, 30000
GO

-- STEP10:执行没有采用分区表的数据库表过程
EXEC [dbo].[Test_GetTestMasterB] 10, 30000
GO

[本日志由 MONO 于 编辑]
文章来自: 本站原创
引用通告: 查看所有引用 | 我要引用此文章
Tags: 分区表 SQL 分区函数 分区
评论: 0 | 引用: 0 | 查看次数: 1023
发表评论
你没有权限发表评论!