惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

V
V2EX
量子位
博客园 - 司徒正美
IT之家
IT之家
V
Visual Studio Blog
Apple Machine Learning Research
Apple Machine Learning Research
博客园_首页
Google DeepMind News
Google DeepMind News
Last Week in AI
Last Week in AI
Microsoft Security Blog
Microsoft Security Blog
T
Tailwind CSS Blog
aimingoo的专栏
aimingoo的专栏
GbyAI
GbyAI
Vercel News
Vercel News
B
Blog
大猫的无限游戏
大猫的无限游戏
D
DataBreaches.Net
小众软件
小众软件
罗磊的独立博客
博客园 - 叶小钗
雷峰网
雷峰网
Martin Fowler
Martin Fowler
Hugging Face - Blog
Hugging Face - Blog
WordPress大学
WordPress大学

博客园 - voiow

C#资源汇总 弹出窗口在屏幕中央 Server.CreateObject 的调用失败 - voiow - 博客园 Server 2005之Integration Service简单实例 获取SQL Server数据库里表容量大小 自定义用户控件属性 - voiow - 博客园 使用asp下的adodb.stream 下载文件而不是打开 javascript以list方式封装xml - voiow - 博客园 Dynamic XML from SQL Server - voiow 将数据库存储的附件写到文件夹上面 - voiow - 博客园 如何用javascript拷贝当前页中被选中的文字? - voiow - 博客园 BizTalk使用发送端口组引起的问题解决方法 SQL Server日志清空方法 SQL SERVER 触发器实例 如何设计一个安全的WEBSERVICE 使用BizTalk Server常见问题处理 ASP.NET程序中常用的三十三种代码 浅谈反射与特性在接口系统中的应用(编码表转化) 使用window.createPopup();做的简单下拉菜单
SQL Server 2005表分区的具体实现方法
voiow · 2010-09-04 · via 博客园 - voiow

SQL Server 2005表分区的具体实现方法

    表分区分为水平分区和垂直分区。水平分区将表分为多个表。每个表包含的列数相同,但是行更少。例如,可以将一个包含十亿行的表水平分区成 12 个表,每个小表表示特定年份内一个月的数据。任何需要特定月份数据的查询只需引用相应月份的表。而垂直分区则是将原始表分成多个只包含较少列的表。水平分区是最常用分区方式,本文以水平分区来介绍具体实现方法。

    水平分区常用的方法是根据时期和使用对数据进行水平分区。例如本文例子,一个短信发送记录表包含最近一年的数据,但是只定期访问本季度的数据。在这种情况下,可考虑将数据分成四个区,每个区只包含一个季度的数据。

    创建文件组

    建立分区表先要创建文件组,而创建多个文件组主要是为了获得好的 I/O 平衡。一般情况下,文件组数最好与分区数相同,并且这些文件组通常位于不同的磁盘上。每个文件组可以由一个或多个文件构成,而每个分区必须映射到一个文件组。一个文件组可以由多个分区使用。为了更好地管理数据(例如,为了获得更精确的备份控制),对分区表应进行设计,以便只有相关数据或逻辑分组的数据位于同一个文件组中。使用 ALTER DATABASE,添加逻辑文件组名:

    ALTER DATABASE [DeanDB] ADD FILEGROUP [FG1]

    DeanDB为数据库名称,FG1文件组名。创建文件组后,再使用 ALTER DATABASE 将文件添加到该文件组中:

    ALTER DATABASE [DeanDB] ADD FILE ( NAME = N'FG1', FILENAME = N'C:DeanDataFG1.ndf' , SIZE = 3072KB , FILEGROWTH = 1024KB ) TO FILEGROUP [FG1]

    类似的建立四个文件和文件组,并把每一个存储数据的文件放在不同的磁盘驱动器里。

    创建分区函数

    创建分区表必须先确定分区的功能机制,表进行分区的标准是通过分区函数来决定的。创建数据分区函数有RANGE “LEFT | / RIGHT”两种选择。代表每个边界值在局部的哪一边。例如存在四个分区,则定义三个边界点值,并指定每个值是第一个分区的上边界 (LEFT) 还是第二个分区的下边界 (RIGHT)[1]。代码如下:

    CREATE PARTITION FUNCTION [SendSMSPF](datetime) AS RANGE RIGHT FOR VALUES ('20070401', '20070701', '20071001')

    创建分区方案

    创建分区函数后,必须将其与分区方案相关联,以便将分区指向至特定的文件组。就是定义实际存放数据的媒体与各数据块的对应关系。多个数据表可以共用相同的数据分区函数,一般不共用相同的数据分区方案。可以通过不同的分区方案,使用相同的分区函数,使不同的数据表有相同的分区条件,但存放在不同的媒介上。创建分区方案的代码如下:

    CREATE PARTITION SCHEME [SendSMSPS] AS PARTITION [SendSMSPF] TO ([FG1], [FG2], [FG3], [FG4])

    创建分区表

    建立好分区函数和分区方案后,就可以创建分区表了。分区表是通过定义分区键值和分区方案相联系的。插入记录时,SQL SERVER会根据分区键值的不同,通过分区函数的定义将数据放到相应的分区。从而把分区函数、分区方案和分区表三者有机的结合起来。创建分区表的代码如下:

  CREATE TABLE SendSMSLog

  ([ID] [int] IDENTITY(1,1) NOT NULL,

  [IDNum] [nvarchar](50) NULL,

  [SendContent] [text] NULL

  [SendDate] [datetime] NOT NULL,

  ) ON SendSMSPS(SendDate)

    查看分区表信息

    系统运行一段时间或者把以前的数据导入分区表后,我们需要查看数据的具体存储情况,即每个分区存取的记录数,那些记录存取在那个分区等。我们可以通过$partition.SendSMSPF来查看,代码如下:

  SELECT $partition.SendSMSPF(o.SendDate)

  AS [Partition Number]

  , min(o.SendDate) AS [Min SendDate]

  , max(o.SendDate) AS [Max SendDate]

  , count(*) AS [Rows In Partition]

  FROM dbo.SendSMSLog AS o

  GROUP BY $partition.SendSMSPF(o.SendDate)

  ORDER BY [Partition Number]  

    维护分区

    分区的维护主要设计分区的添加、减少、合并和在分区间转换。可以通过ALTER PARTITION FUNCTION的选项SPLIT,MERGE和ALTER TABLE的选项SWITCH来实现。SPLIT会多增加一个分区,而MEGRE会合并或者减少分区,SWITCH则是逻辑地在组间转换分区.

track:http://club.youshang.com/home.php?mod=space&uid=6804&do=blog&id=35862

另见:表分区实现步骤:

分区表对于将大表按照业务逻辑分拆成若干小表非常有用,这将缩小每次查询的数据范围和提高查询的IO并发,从而达到提高大表查询效率的目的。
但是数据查询的业务逻辑必须符合分区规则,否则将频繁出现多分区合并查询场景,这反而会极大地降低查询效率。
分区表的创建流程主要是:创建分区函数->根据分区函数创建分区架构->根据分区架构创建分区表。
下面是具体实现步骤和代码(首先建立一个测试数据库ArticlesDB,数据文件存放在D:\Data\下,当然可以自行修改):

--添加用于存放分区表的文件组
Alter Database [ArticlesDB] Add FileGroup [Slave];
Go

--添加用于存放分区表的数据文件
Alter Database [ArticlesDB] Add File (NAME = N'ArticlesDBSlave', FileName = N'D:\Data\ArticlesSlave.ndf') To FileGroup [Slave];
Go

Use ArticlesDB;

--创建分区函数
Create Partition Function pfuArticles (DateTime)
As Range Right
For Values('20060101', '20070101', '20080101', '20090101', '20100101');
Go

--创建分区架构,文件组数量必须等于分区数
Create Partition Scheme pscArticles
As Partition pfuArticles
To(Slave, Slave, Slave, Slave, Slave, Slave);
Go

--创建分区表,分区字段必须包含在主键中
CREATE TABLE [dbo].[pArticles]
(
    [ArticleID] [int] IDENTITY(1,1) NOT NULL,
    [AddTime] [datetime] Not NULL,
    [Audit] [bit] NULL,
    [ArticleTitle] [nvarchar](100) NULL,
    [ArticleContent] [nvarchar](max) NULL,
    CONSTRAINT [PK_pArticles] PRIMARY KEY CLUSTERED
    (
        [AddTime] Desc,
        [ArticleID] DeSC
    )
)   
ON pscArticles(AddTime);
Go

ALTER TABLE [dbo].[pArticles]
ADD CONSTRAINT [DF_pArticles_AddTime] DEFAULT (getdate()) FOR [AddTime];
Go

ALTER TABLE [dbo].[pArticles]
ADD CONSTRAINT [DF_pArticles_Audit] DEFAULT ((0)) FOR [Audit];
Go

--创建非聚集分区索引
Create NonClustered Index [IX|AddTime(D),ArticleID(D),Audit|ArticleTitle]
On pArticles
(
    AddTime Desc,
    ArticleID Desc,
    Audit
)
Include
(
    ArticleTitle
)
On pscArticles(AddTime);
Go

--增加分区架构使用的文件组,每个分区对应一个文件组
Alter Partition Scheme pscArticles
Next Used Slave;
Go

--分割分区,必须先增加分区架构使用的文件组
Alter Partition Function pfuArticles() Split Range('20050101');
Go

--查看每个分区的记录数
Select
    $Partition.pfuArticles(AddTime) As [Partition],
    Count(ArticleID) As RecordCount
From pArticles
Group By $Partition.pfuArticles(AddTime)
Order By [Partition];
Go

--合并分区,等同于删除分区
Alter Partition Function pfuArticles() Merge Range('20050101');
Go

--切换分区
Alter Table pArticles Switch Partition 1 To pArticles20070101;
Go

--快速清理分区数据(三个月前的分区数据)
CREATE TABLE [dbo].[pArticlesTemp]
(
    [ArticleID] [int] IDENTITY(1,1) NOT NULL,
    [AddTime] [datetime] Not NULL,
    [Audit] [bit] NULL,
    [ArticleTitle] [nvarchar](100) NULL,
    [ArticleContent] [nvarchar](max) NULL,
    CONSTRAINT [PK_pArticlesTemp] PRIMARY KEY CLUSTERED
    (
        [AddTime] Desc,
        [ArticleID] DeSC
    )
)   
ON Slave;
Go

Declare @Date Char(8);
Set @Date = Left(Convert(Char(8), DateAdd(m, -4, GetDate()), 112), 6) + '01';

Declare @PartitionID Int;
Select @PartitionID = $PARTITION.pfuArticles(@Date);

Alter Table pArticles Switch Partition @PartitionID To pArticlesTemp;

Truncate Table pArticlesTemp;

Alter Partition Function pfuArticles() Merge Range(@Date);