码迷,mamicode.com
首页 > 数据库 > 详细

34. SQL - 分区表

时间:2015-04-03 19:33:57      阅读:240      评论:0      收藏:0      [点我收藏+]

标签:数据库系统   企业信息化   触发器   工作者   决策者   

 

分区表概述:

 

大凡在用系和数据中行走江湖多年的朋友,都会面数据统计、分析以及档的问题,企信息化程加速了各种数据的极具增,商智能(BI)的出施着实给信息工作者和决策者来了妙的体,但从 OLTP 向 OLAP系数据是很疼的事,常常需要数分或数小,解决问题的技之一便是分区表,一旦施了分区表,这样的操作往往只需几秒,太兴奋了。而大型表或索引经过分区后更容易行管理,因为这样可以快速高效地管理和访问数据子集,同时维护数据集合的完整性。分区表的数据分布于一个数据中的多个文件组单元中,数据是按水平方式分区的(数据分区的多种方式会在分区表前述),因此一个表的某些行映射到某个分区,而另外一些行映射到另外某个分区,以此推。当数据查询或更新,表将被视为单逻辑实体,所以在数据访问层你会感访问普通表一,而好就在于可以查询想要的某个分区,而不必描整个表。有一点必明白,个表的所有分区都必位于同一个数据中。

分区表支持和准表相关的所有属性和功能,包括束、默认值标识时间以及触器等。决定是否实现分区主要取决于表当前的大小或将来的大小以及查询维护操作的完善程度。

通常,如果某个大型表同时满足下列两个条件,可能适于行分区:

1 、表包含或将包含以多种不同方式使用的大量数据

2 、维护维护

例如,

如果当前年份或当前月份的数据主要SELECT INSERTUPDATE DELETE 操作,而以前年份或以前月份的数据主要SELECT 查询如果按年份或月行分区,表的管理要容易些,因时对表的维护操作只针对一个数据子集。如表没有分区,那么就需要整个数据集些操作,这样就会消耗大量源。所以常常根据日期和分类对行分区,当然利用某个标识ID 也是很好的选择。例如,子商数据的某表可能包含了近6 年的数据,但是只定期访问本年度或某个月的数据,那么就可以按年份或月份分区,而另外一表包含了近几十种型商品的订单那么此可以每种型商品分一个区。

一般而言,衡量大型表是以数据为标准的,但于适合分区的大型表,衡量大型表更重要的是数据访问的性能,如果于某些表的访问维护较严重的性能问题,就可以视为大型表,就应该更好的设计和分区来解决性能问题

 

建分区表必须经过如下三个步

1 建分区函数

2 建映射到分区函数的分区方案

3 建使用分区方案的分区表

1)、分区函数:

分区函数是数据中的一个独立象,它将表的行映射到一分区,所以分区函数解决的是HOW 问题,即表如何分区的问题建分区函数,必指明数据分区的界点以及分区依据列,这样便知道如何表或索引行分区。分区函数的法如下:

CREATE PARTITION FUNCTION partition_function_name(input_parameter_type)

AS RANGE [ LEFT | RIGHT]

FOR VALUES ( [boundary_value [ ,...n ] ] )

[ ; ]

2)、分区方案

表和索引行分区的第二步是建分区方案。分区方案定了一个特定的分区函数将使用的物理存储结构(其就是文件),或者是分区方案将分区函数生成的分区映射到我的一文件。所以分区方案解决的是Where 问题,即表的各个分区在哪里存问题

分区方案的法如下:

CREATE PARTITION SCHEMEpartition_scheme_name

AS PARTITION partition_function_name

[ ALL ] TO ( { file_group_name|[PRIMARY ] } [ ,...n ] )

[ ; ]

分区方案例子1:下面的代建一个分区函数,然后再个分区函数使用的分区方案,个分区方案将每个分区映射到不同文件。代如下:

create partition function MyPF1(int)

as range left

for values(500000,1000000,1500000)

go

create partition scheme MyPS1

as partition MyPF1

to (fg1, fg2, fg3, fg4)

分区方案例子2:下面的代建一个分区函数,然后再个分区函数使用的分区方案,个分区方案将多个分区映射到同一个文件。代如下:

create partition function MyPF2(int)

as range left

for values(500000,1000000,1500000)

go

create partition scheme MyPS2

as partition MyPF2

to (fg1, fg1, fg1, fg2)

分区方案例子3:下面的代建一个分区函数,然后再个分区函数使用的分区方案,个分区方案将所有分区映射到同一个文件。代如下:

create partition function MyPF3 (int)

as range left

for values(500000,1000000,1500000)

go

create partition scheme MyPS3

as partition MyPF3

all to (fg1)

分区方案例子4:下面的代建一个分区函数,然后再个分区函数使用的分区方案,个分区方案指定了“NEXT USED”文件。代如下:

create partition function MyPF4(int)

as range left

for values(500000,1000000,1500000) --4个分区

go

create partition scheme MyPS4

as partition MyPF4

to (fg1, fg2, fg3, fg4, fg5) --5 个文件

那么文件fg5 将自标记为NEXT USED”文件

分区方案例子5:下面的代建一个分区函数,然后再个分区函数使用的分区方案,个分区方案指定了“[primary]”文件。代如下:

create partition function MyPF5(datetime)

range right

for values(‘2008/01/01‘, ‘2009/01/01‘)

go

create partition scheme MyPS5

as partition MyPF5

to([primary], fg1, fg2)

最后必明白一点,一表最多只能有1000 个分区。

3)、分区表

在分区函数和分区方案建完成后,建分区表的准工作已完成。我看一个完整的例子,代如下:

--建分区函数

create partition function MyPF(datetime)

range right

for values(‘2007-1-1‘, ‘2008-1-1‘)

go

--建分区方案

create partition scheme MyPS

as partition MyPF

to(fg1, fg2, fg3)

go

--建分区表

create table orders

(

OrderID int identity(1,1) primary key,

OrderDate datetime,

CustID varchar(10)

)

on MyPS(OrderDate)

4)DEMO1:新建一个表,写入100万条记录,要求<200000 记录FG1200000<&<600000记录FG2>600000记录FG3

demo_db 数据中文件及文

USE [demo_db]

GO

ALTER DATABASE demo_db

REMOVE FILE file1

GO

ALTER DATABASE [demo_db]

REMOVE FILEGROUP fg1

GO

ALTER DATABASE demo_db

REMOVE FILE file2

GO

ALTER DATABASE [demo_db]

REMOVE FILEGROUP fg2

GO

ALTER DATABASE demo_db

REMOVE FILE file3

GO

ALTER DATABASE demo_db

REMOVE FILEGROUP fg3

GO

分区表建流程:

建文件 → 建文件(指定属于那个文件建分区函数(分区的条件)建分区方案 → 生产环境中(将需分区的文件重命名) → 新增一个table,配置其onschema,所在的分区分案 → 从旧表入数据到新表验证

--1建立我要使用的数据,最重要的是建立多个文件

CREATE DATABASE Sales ON PRIMARY

(

NAME = N‘Sales‘,

FILENAME = N‘C:\Sales.mdf‘,

SIZE = 3MB,

MAXSIZE = 100MB,

FILEGROWTH = 10%

),

FILEGROUP FG1

(

NAME = N‘File1‘,

FILENAME = N‘C:\File1.ndf‘,

SIZE = 1MB,

MAXSIZE = 100MB,

FILEGROWTH = 10%

),

FILEGROUP FG2

(

NAME = N‘File2‘,

FILENAME = N‘C:\File2.ndf‘,

SIZE = 1MB,

MAXSIZE = 100MB,

FILEGROWTH = 10%

),

FILEGROUP FG3

(

NAME = N‘File3‘,

FILENAME = N‘C:\File3.ndf‘,

SIZE = 1MB,

MAXSIZE = 100MB,

FILEGROWTH = 10%

)

LOG ON

(

NAME = N‘Sales_Log‘,

FILENAME = N‘C:\Sales_Log.ldf‘,

SIZE = 1MB,

MAXSIZE = 100MB,

FILEGROWTH = 10%

)

GO

--2、建立分区函数,里我建立三个分区。how(如何数据行分区)

USE Sales

go

CREATE PARTITION FUNCTION [PF1] (int)

AS RANGE RIGHT

FOR VALUES (200000,600000)

/*

注意CREATEPARTITION FUNCTION 建立数据分割函数有RANGE LEFT|RIGHT 两种选择代表每个是在局部的哪一,即符合该值记录是在局部的哪一,例如:

参数 partition1 2 3

LEFT-<<=20W 20w<<=60W 60w 以上

RIGHT-<<20W 20w<=<60W 60w 以上()

*/

--3建分区方案,关到分区函数where(在哪里数据行分区)

create partition scheme ps1

as partition PF1

to (FG1,FG2,FG3)

--4数据分区的测试

CREATE TABLE tbl

(

c1 int identity(1,1),

c2 int,c3 nvarchar(100)

)

on PS1(c1)

--5、通写入测试数据

DECLARE @i int

SET @i=1

WHILE @i<21

BEGIN

INSERT tbl(c2,c3) SELECT c2,c3 FROM tbl

SET @i=@i+1

END

--6、最后我们查询数据是否真的被分割

SELECT $PARTITION.[PF1](c1) as [partition],*

FROM tbl where c1 in (1,200000,200001,599999,600000,600001)

5)、DEMO2timeRecords 行分区,并按日期行分区

--1建一个测试数据,并3 个文件3 个文件,将3 个文件指定到文件.

CREATE DATABASE [test] ON PRIMARY

( NAME = N‘test‘,

FILENAME = N‘C:\ProgramFiles\Microsoft SQL

Server\MSSQL10.MSSQLSERVER\MSSQL\DATA\test.mdf‘,

SIZE = 75776KB ,

MAXSIZE = UNLIMITED,

FILEGROWTH = 1024KB ),

FILEGROUP [FGROUP1]

( NAME = N‘fgroup1‘,

FILENAME = N‘C:\ProgramFiles\Microsoft SQL

Server\MSSQL10.MSSQLSERVER\MSSQL\DATA\fgroup1.ndf‘,

SIZE = 2048KB ,

MAXSIZE = UNLIMITED,

FILEGROWTH = 1024KB ),

FILEGROUP [FGROUP2]

 ( NAME = N‘fgroup2‘,

FILENAME = N‘C:\ProgramFiles\Microsoft SQL

Server\MSSQL10.MSSQLSERVER\MSSQL\DATA\fgroup2.ndf‘,

SIZE = 2048KB ,

MAXSIZE = UNLIMITED,

FILEGROWTH = 1024KB ),

FILEGROUP [FGROUP3]

( NAME = N‘fgroup3‘,

FILENAME = N‘C:\ProgramFiles\Microsoft SQL

Server\MSSQL10.MSSQLSERVER\MSSQL\DATA\fgroup3.ndf‘,

SIZE = 2048KB ,

MAXSIZE = UNLIMITED,

FILEGROWTH = 1024KB )

LOG ON

( NAME = N‘test_log‘,

FILENAME = N‘C:\ProgramFiles\Microsoft SQL

Server\MSSQL10.MSSQLSERVER\MSSQL\DATA\test_log.ldf‘,

SIZE = 102144KB ,

MAXSIZE = 2048GB ,

FILEGROWTH = 10%)

GO

--2建分区函数:

按日期行分区,要求<2011-07-01 的一个分区,在2011-07-01 2011-07-31在一个分区,>=2011-08-01 在一个分区

create partition function PF1 (datetime)

as range right for values

(‘2011-07-01‘,

‘2011-08-01‘)

--3建分区方案

create partition scheme PS1

as partition PF1

to (FGROUP1,FGROUP2,FGROUP3)

GO

--4、从MYDB 中,将timerecords表复制到test 数据

select *

into timerecords

from mydb.dbo.TimeRecords

--5建一个空白的timerecords 表,格式与timerecords_bak ,指定表存在新建的存方案PS1

CREATE TABLE [dbo].[timerecords]

 (

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

[clock_id] [int] NOT NULL,

[emp_id] [nvarchar](12) NULL,

[join_id] [int] NULL,

[depart_id] [nvarchar](30) NULL,

[card_id] [nvarchar](16) NOT NULL,

[sign_time] [datetime] NOT NULL,

[mark] [tinyint] NULL,

[flag] [int] NULL,

[kind] [int] NULL,

[reader_no] [int] NULL,

[door_flag] [int] NULL,

[bill_id] [nvarchar](20) NULL,

[checker] [nvarchar](16) NULL,

[check_date] [datetime] NULL,

[op_user] [nvarchar](16) NULL,

[op_date] [datetime] NULL,

[audit] [bit] NULL,

[memo] [nvarchar](200) NULL,

[order_time] [datetime] NULL,

[order_money] [money] NULL,

[luocard] [bit] NULL,

[bcancel] [bit] NULL,

[is_days] [int] NULL

)

ON PS1(sign_time)

GO

--6、写入数据,由于timerecords表中第一列id 自增列,因此在写入数据,需去掉第一列id 才能从timerecords_bak中引入数据.

INSERT INTO [test].[dbo].[timerecords]

([clock_id]

,[emp_id]

,[join_id]

,[depart_id]

,[card_id]

,[sign_time]

,[mark]

,[flag]

,[kind]

,[reader_no]

,[door_flag]

,[bill_id]

,[checker]

,[check_date]

,[op_user]

,[op_date]

,[audit]

,[memo]

,[order_time]

,[order_money]

,[luocard]

,[bcancel]

,[is_days])

select

[clock_id]

,[emp_id]

,[join_id]

,[depart_id]

,[card_id]

,[sign_time]

,[mark]

,[flag]

,[kind]

,[reader_no]

,[door_flag]

,[bill_id]

,[checker]

,[check_date]

,[op_user]

,[op_date]

,[audit]

,[memo]

,[order_time]

,[order_money]

,[luocard]

,[bcancel]

,[is_days]

from timerecords_bak

GO

--7看分区的果:

select $partition.PF1(SIGN_time)

as partition, *

from timerecords

where CONVERT(char(10),sign_time,121) in (‘2011-06-10‘,

‘2011-06-30‘,

‘2011-07-01‘,

‘2011-07-31‘,

‘2011-08-01‘,

‘2011-08-31‘)

and emp_id = ‘P1003101‘

order by sign_time


本文出自 “Ricky's Blog” 博客,请务必保留此出处http://57388.blog.51cto.com/47388/1628081

34. SQL - 分区表

标签:数据库系统   企业信息化   触发器   工作者   决策者   

原文地址:http://57388.blog.51cto.com/47388/1628081

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!