什么是表分区
SQL Server使用三种不同类型的文件存储数据,它们分别是.mdf、.ndf和.ldf。主要数据存储在
.mdf文件中,比如表,索引,存储过程等。.ndf文件也用于储存这些数据。.ldf文件用于存储操作日志。
表默认存储在.mdf文件中。更新表时SQL Server会对表锁。那么其它的操作必须等待正在更新操作完成。
如果一个表很大,那么无论是查询操作还是更新操作,性能都会很差。如果将表分别存储在物理上独立但逻辑上连续的
分区中,那么SQL Server可以大幅优化查询操作和更新操作的性能。
分区的优点
1、提高可伸缩性和可管理性:在SQL Server 2005中建立分区,改善大型表以及具有各种访问模式的表的可伸缩性和可管理性。
2、提高性能
3、只有将数据分区分到不同的磁盘上,才会有较大的提升。
4、因为在运行涉及表间联接的查询时,多个磁头可以同时读取数据。
分区时需注意事项
1、虽然分区可以带来众多的好处,但是同时也增加了实现对象的管理费用和复杂性。因此在进行分区之前要首先仔细的考虑以确定是否应为对象进行分区。
2、在确定了为对象进行分区后,下一步就要确定分区键和分区数。要确定分区数据,应先评估您的数据中是否存在逻辑分组和模式。
3、确定是否应使用多个文件分组。为了有助于优化性能和维护,应使用文件组分离数据。文件组是数据库数据文件的逻辑组合,它可以对数据文件进行管理和分配,以便提高数据库文件的并发访问效率。
分区的实现
1.创建文件组:alter database <数据库名> add filegroup <文件组名>
2.创建数据文件到文件组:
alter database <数据库名称> add file <数据标识> to filegroup <文件组名称>
--<数据标识> (name:文件名,fliename:物理路径文件名,size:文件初始大小kb/mb/gb/tb,filegrowth:文件自动增量kb/mb/gb/tb/%,maxsize:文件可以增加到的最大大小kb/mb/gb/tb/unlimited)
3.右键要分区的表,存储选项中创建分区
4.打开创建分区向导,下一步
5.选择列后下一步,新建分区函数,写入函数名称,下一步
6.新建分区方案,写入方案名称
7.创建分区规则
左边界右边界:就是把临界值划分给上一个分区还是下一个分区。一个小于号,一个小于等于号。
8.下一步,得到分区语句 及 方案,执行后,分区完成。
SQL语句实现
1.分区函数
指定分依据区列(依据列唯一),分区数据范围规则,分区数量,然后将数据映射到一组分区上。
创建语法:
create partition function 分区函数名(<分区列类型>) as range [left/right]
for values (每个分区的边界值,....)然而,分区函数只定义了分区的方法,此方法具体用在哪个表的那一列上,则需要在创建表或索引是指定。
删除语法:
--删除分区语法drop partition function <分区函数名>需要注意的是,只有没有应用到分区方案中的分区函数才能被删除。
2.分区方案
指定分区对应的文件组。
创建语法:
--创建分区方案语法create partition scheme <分区方案名称> as partition <分区函数名称> [all]to (文件组名称,....)分区函数必须关联分区方案才能有效,然而分区方案指定的文件组数量必须与分区数量一致,哪怕多个分区存放在一个文件组中。
删除语法:
--删除分区方案语法drop partition scheme<分区方案名称>只有没有分区表,或索引使用该分区方案是,才能对其删除。
3.分区表
创建语法:
--创建分区表语法create table <表名> ( <列定义>)on<分区方案名>(分区列名)如果在表中创建主键或唯一索引,则分区依据列必须为该列。
4.分区索引
创建语法:
--创建分区索引语法create <索引分类> index <索引名称> on <表名>(列名)on <分区方案名>(分区依据列名)使用分区索引查询,可以避免多个cpu操作多个磁盘时产生的冲突。
执行完成后,右键要分区的表,选择现有的分区函数、分区方案。
分区表明细信息
1.查看分区依据列的指定值所在的分区
--查询分区依据列为10000014的数据在哪个分区上select $partition.分区函数名称(2000000) --返回值是2,表示此值存在第2个分区2.查看分区表中,每个非空分区存在的行数
--查看分区表中,每个非空分区存在的行数select $partition.分区函数名称(列名称) as partitionNum,count(*) as recordCountfrom 表名group by $partition.分区函数名称(列名称)3.查看指定分区中的数据记录
---查看指定分区中的数据记录select * from 表名 where $partition.分区函数名称(列名称)=2结果:数据从1000001开始到200W结束
分区的拆分及合并与数据移动
1.拆分分区
在分区函数中新增一个边界值,即可将一个分区变为2个。
--分区拆分
alter partition function 分区函数名称()
split range(N'1500000') --将第二个分区拆为2个分区注意:如果分区函数已经指定了分区方案,则分区数需要和分区方案中指定的文件组个数保持对应一致。
2.合并分区
与拆分分区相反,去除一个边界值即可。
--合并分区alter partition function 分区函数名称()merge range(N'1500000') --将第二第三分区合并3.分区中的数据移动
你或许会遇到这样的需求,将普通表数据复制到分区表中,或者将分区表中的数据复制到普通表中。
那么移动数据这两个表,则必须满足下面的要求。
- 字段数量相同,对应位置的字段相同
- 相同位置的字段要有相同的属性,相同的类型。
- 两个表在一个文件组中
1.创建表时指定文件组
--创建表create table <表名> ( <列定义>)on <文件组名>
2.从分区表中复制数据到普通表
--将bigorder分区表中的第一分区数据复制到普通表中alter table 表名 switch partition 1 to <普通表名>
3.从普通标中复制数据到分区表中
这里要注意的是要先将分区表中的索引删除,即便普通表中存在跟分区表中相同的索引。
--将普通表中的数据复制到bigorder分区表中的第一分区alter table <普通表名> switch to 表名 partition 1
分区视图
分区视图是先建立带有字段约束的相同表,而约束不同,例如,第一个表的id约束为0--100W,第二表为101万到200万.....依次类推。
创建完一系列的表之后,用union all 连接起来创建一个视图,这个视图就形成啦分区视同。
很简单的,这里我主要是说分区表,就不说分区视图啦。。
查看数据库分区信息
SELECT OBJECT_NAME(p.object_id) AS ObjectName, i.name AS IndexName, p.index_id AS IndexID, ds.name AS PartitionScheme, p.partition_number AS PartitionNumber, fg.name AS FileGroupName, prv_left.value AS LowerBoundaryValue, prv_right.value AS UpperBoundaryValue, CASE pf.boundary_value_on_right WHEN 1 THEN 'RIGHT' ELSE 'LEFT' END AS Range, p.rows AS RowsFROM sys.partitions AS pJOIN sys.indexes AS i ON i.object_id = p.object_id AND i.index_id = p.index_idJOIN sys.data_spaces AS ds ON ds.data_space_id = i.data_space_idJOIN sys.partition_schemes AS ps ON ps.data_space_id = ds.data_space_idJOIN sys.partition_functions AS pf ON pf.function_id = ps.function_idJOIN sys.destination_data_spaces AS dds2 ON dds2.partition_scheme_id = ps.data_space_id AND dds2.destination_id = p.partition_numberJOIN sys.filegroups AS fg ON fg.data_space_id = dds2.data_space_idLEFT JOIN sys.partition_range_values AS prv_left ON ps.function_id = prv_left.function_id AND prv_left.boundary_id = p.partition_number - 1LEFT JOIN sys.partition_range_values AS prv_right ON ps.function_id = prv_right.function_id AND prv_right.boundary_id = p.partition_number WHERE OBJECTPROPERTY(p.object_id, 'ISMSShipped') = 0UNION ALLSELECT OBJECT_NAME(p.object_id) AS ObjectName, i.name AS IndexName, p.index_id AS IndexID, NULL AS PartitionScheme, p.partition_number AS PartitionNumber, fg.name AS FileGroupName, NULL AS LowerBoundaryValue, NULL AS UpperBoundaryValue, NULL AS Boundary, p.rows AS RowsFROM sys.partitions AS pJOIN sys.indexes AS i ON i.object_id = p.object_id AND i.index_id = p.index_idJOIN sys.data_spaces AS ds ON ds.data_space_id = i.data_space_idJOIN sys.filegroups AS fg ON fg.data_space_id = i.data_space_idWHERE OBJECTPROPERTY(p.object_id, 'ISMSShipped') = 0ORDER BY ObjectName, IndexID, PartitionNumber