SQL Server表分区的NULL值问题

原文:SQL Server表分区的NULL值问题

SQL Server表分区的NULL值问题

SQL Server表分区只支持range分区这一种类型,往往会被大家吐槽

人家MySQL支持四种类型:RANGE分区、LIST分区、HASH分区、KEY分区

 

 

共同点是MySQL跟SQL Server也有分区对齐的问题,都是水平切分,大家都允许分区列存在NULL值

 

这次我们测试SQL Server表分区的分区列的NULL值,究竟NULL值是被存放在哪个区间,以前一直没有注意

测试脚本

--1.创建文件组
ALTER DATABASE [sss]
ADD FILEGROUP [FG_TinyBlog_Id_01]

ALTER DATABASE [sss]
ADD FILEGROUP [FG_TinyBlog_Id_02]

ALTER DATABASE [sss]
ADD FILEGROUP [FG_TinyBlog_Id_03]

ALTER DATABASE [sss]
ADD FILEGROUP [FG_TinyBlog_Id_04]

ALTER DATABASE [sss]
ADD FILEGROUP [FG_TinyBlog_Id_05]

--2.创建文件
ALTER DATABASE [sss]
ADD FILE
(NAME = N'FG_TinyBlog_Id_01_data',FILENAME = N'E:\DataBase\sss\FG_TinyBlog_Id_01_data.ndf',SIZE = 96MB, FILEGROWTH = 24MB )
TO FILEGROUP [FG_TinyBlog_Id_01];

ALTER DATABASE [sss]
ADD FILE
(NAME = N'FG_TinyBlog_Id_02_data',FILENAME = N'E:\DataBase\sss\FG_TinyBlog_Id_02_data.ndf',SIZE = 96MB, FILEGROWTH = 24MB )
TO FILEGROUP [FG_TinyBlog_Id_02];

ALTER DATABASE [sss]
ADD FILE
(NAME = N'FG_TinyBlog_Id_03_data',FILENAME = N'E:\DataBase\sss\FG_TinyBlog_Id_03_data.ndf',SIZE = 96MB, FILEGROWTH = 24MB )
TO FILEGROUP [FG_TinyBlog_Id_03];

ALTER DATABASE [sss]
ADD FILE
(NAME = N'FG_TinyBlog_Id_04_data',FILENAME = N'E:\DataBase\sss\FG_TinyBlog_Id_04_data.ndf',SIZE = 96MB, FILEGROWTH = 24MB )
TO FILEGROUP [FG_TinyBlog_Id_04];

ALTER DATABASE [sss]
ADD FILE
(NAME = N'FG_TinyBlog_Id_05_data',FILENAME = N'E:\DataBase\sss\FG_TinyBlog_Id_05_data.ndf',SIZE = 96MB, FILEGROWTH = 24MB )
TO FILEGROUP [FG_TinyBlog_Id_05];

--3.创建分区函数
CREATE PARTITION FUNCTION
Fun_TinyBlog_Id(INT) AS
RANGE LEFT
FOR VALUES(-10,0,1,6)

--4.创建分区方案
CREATE PARTITION SCHEME
[Sch_TinyBlog_Id] AS
PARTITION [Fun_TinyBlog_Id]
TO([FG_TinyBlog_Id_01],[FG_TinyBlog_Id_02],[FG_TinyBlog_Id_03],[FG_TinyBlog_Id_04],[FG_TinyBlog_Id_05])

View Code

插入测试数据

USE [sss]

CREATE TABLE TinyBlog(id INT  NULL,NAME VARCHAR(100))
 ON [Sch_TinyBlog_Id](id)

SELECT * FROM TinyBlog ORDER BY id 

INSERT INTO [dbo].[TinyBlog]
        ( [id], [NAME] )
VALUES  ( NULL, -- id - int
          '3232'  -- NAME - varchar(100)
          )

INSERT INTO [dbo].[TinyBlog]
        ( [id], [NAME] )
VALUES  ( -2, -- id - int
          '-2'  -- NAME - varchar(100)
          )

INSERT INTO [dbo].[TinyBlog]
        ( [id], [NAME] )
VALUES  ( 66, -- id - int
          '66'  -- NAME - varchar(100)
          )

INSERT INTO [dbo].[TinyBlog]
        ( [id], [NAME] )
VALUES  ( 0, -- id - int
          '0'  -- NAME - varchar(100)
          )

INSERT INTO [dbo].[TinyBlog]
        ( [id], [NAME] )
VALUES  ( -30, -- id - int
          '-30'  -- NAME - varchar(100)
          )

 

表数据如下

SELECT * FROM TinyBlog ORDER BY id 

 

分区分布

--查看分区架构文件组分布
SELECT  CONVERT(VARCHAR(MAX), ps.name) AS partition_scheme ,
        p.partition_number ,
        CONVERT(VARCHAR(MAX), ds2.name) AS filegroup ,
        CONVERT(VARCHAR(MAX), ISNULL(v.value, ''), 120) AS range_boundary ,
        STR(p.rows, 9) AS rows
FROM    sys.indexes i
        JOIN sys.partition_schemes ps ON i.data_space_id = ps.data_space_id
        JOIN sys.destination_data_spaces dds ON ps.data_space_id = dds.partition_scheme_id
        JOIN sys.data_spaces ds2 ON dds.data_space_id = ds2.data_space_id
        JOIN sys.partitions p ON dds.destination_id = p.partition_number
                                 AND p.object_id = i.object_id
                                 AND p.index_id = i.index_id
        JOIN sys.partition_functions pf ON ps.function_id = pf.function_id
        LEFT JOIN sys.Partition_Range_values v ON pf.function_id = v.function_id
                                                  AND v.boundary_id = p.partition_number
                                                  - pf.boundary_value_on_right
WHERE   i.object_id = OBJECT_ID('TinyBlog')
        AND i.index_id IN ( 0, 1 )
ORDER BY p.partition_number

--分区区间
--SELECT  *  FROM    sys.partition_range_values

View Code

 

分区情况

--分区情况
SELECT  c.* ,
        b.[groupname] AS '分区方案对应的文件组名称' ,
        d.name '当前分区函数对应的分区方案'
FROM    sys.destination_data_spaces AS a
        INNER JOIN sysfilegroups AS b ON a.[data_space_id] = b.[groupid]
        INNER JOIN ( SELECT $PARTITION.Fun_TinyBlog_Id(id) AS 分区编号 ,
                            MIN(id) AS Min_value ,
                            MAX(id) AS Max_value ,
                            COUNT(id) AS 记录数
                     FROM   [dbo].[TinyBlog]
                     GROUP BY $PARTITION.Fun_TinyBlog_Id(id)
                   ) AS c ON c.[分区编号] = a.[destination_id]
        INNER JOIN sys.partition_schemes AS d ON a.[partition_scheme_id] = d.data_space_id
ORDER BY c.[分区编号]

View Code

 

第二个视图直接把NULL值忽略了

 

根据第一个视图,我们画出一个总结图

 

分析一下

 

 



总结

结论其实很清晰,分区列不要允许NULL,如果允许列,那么我们交换分区归档数据的时候就会有麻烦了,因为无法判断分区列是NULL值的那些数据行是老数据还是新数据

 

 

 

相关文章:

http://www.cnblogs.com/gaizai/archive/2010/11/05/1870071.html

https://msdn.microsoft.com/zh-cn/library/ms187802.aspx

 

 

如有不对的地方,欢迎大家拍砖o(∩_∩)o 

时间: 2024-10-22 08:53:25

SQL Server表分区的NULL值问题的相关文章

SQL Server 表分区(partitioned table/Data Partitioning)

server Partitioned Table 可伸缩性性是数据库管理系统的一个很重要的方面,在SQL Server 2005中可伸缩性方面提供了表分区功能. 其实对于有关系弄数据库产品来说,对表.数据库和服务器进行数据分区的从而提供大数据量的支持并不是什么新鲜事,但 SQL Server 2005 提供了一个新的体系结构功能,用于对数据库中的文件组进行表分区.水平分区可根据分区架构,将一个表划分为几个较小的分组.表分区功能是针对超大型数据库(从数百吉字节到数千吉字节或更大)而设计的.超大型数

SQL Server 表分区

什么是表分区 一般情况下,我们建立数据库表时,表数据都存放在一个文件里. 但是如果是分区表的话,表数据就会按照你指定的规则分放到不同的文件里,把一个大的数据文件拆分为多个小文件,还可以把这些小文件放在不同的磁盘下由多个cpu进行处理.这样文件的大小随着拆分而减小,还得到硬件系统的加强,自然对我们操作数据是大大有利的. 所以大数据量的数据表,对分区的需要还是必要的,因为它可以提高select效率,还可以对历史数据经行区分存档等.但是数据量少的数据就不要凑这个热闹啦,因为表分区会对数据库产生不必要的

SQL Server已分区索引的特殊指导原则(3)

一.前言 在MSDN上看到一篇关于SQL Server 表分区的文档:已分区索引的特殊指导原则,如果你对表分区没有实战经验的话是比较难理解文档里面描述的意思.这里我就里面的一些概念进行讲解,方便大家的交流. SQL Server 解读[已分区索引的特殊指导原则](1)- 索引对齐 SQL Server 解读[已分区索引的特殊指导原则](2)- 唯一索引分区 二.解读 [对非聚集索引进行分区] "对唯一的非聚集索引进行分区时,索引键必须包含分区依据列.对非唯一的非聚集索引进行分区时,默认情况下 S

SQL Server已分区索引的特殊指导原则(2)- 唯一索引分区

一.前言 在MSDN上看到一篇关于SQL Server 表分区的文档:已分区索引的特殊指导原则,如果你对表分区没有实战经验的话是比较难理解文档里面描述的意思.这里我就里面的一些概念进行讲解,方便大家的交流. 二.解读 [对唯一索引进行分区] "对唯一索引(聚集或非聚集)进行分区时,必须从唯一索引键使用的分区依据列中选择分区依据列.此限制将使 SQL Server 只调查单个分区,以确保表中不存在重复的新键值.如果分区依据列不可能包含在唯一键中,则必须使用 DML 触发器,而不是强制实现唯一性.&

深入浅出SQL Server 2008 分区函数和分区表

原文:深入浅出SQL Server 2008 分区函数和分区表     当我们数据量比较大的时候,我们需要将大型表拆分为多个较小的表,则只访问部门数据的查询就可以更快的运行,基本原理就是,因为要扫描的数据变的更小.维护任务(例如,重新生成索引或备份表)也可以更快的运行.    我们可以再不通过将表物理放置在多个磁盘驱动器上来拆分表的情况下获取分区.如果将某个表放置在一个物理驱动器上,将相关表放置在另一个驱动器上,则可以提高查询性能,因为当运行涉及表间连接的查询时,多个磁盘头同时读取数据.可以使用

SQL Server锁分区特性引发死锁解析

原文:SQL Server锁分区特性引发死锁解析 锁分区技术使得SQL Server可以更好地应对并发情形,但也有可能带来负面影响,这里通过实例为大家介绍,分析由于锁分区造成的死锁情形. 前段时间园友@JentleWang在我的博客锁分区提升并发,以及锁等待实例中问及锁分区的一些特性造成死锁的问题,这类死锁并不常见,我们在这里仔细分析下.不了解锁分区技术的朋友请先看下我的锁分区那篇实例. Code(执行测试脚本时请注意执行顺序,说明) 步骤1 创建测试数据 use tempdb go creat

SQL Server返回最后一个标识值的三个函数:IDENT_CURRENT、@@IDENTITY、SCOPE_IDENTITY

昨天有人在群里讨论SQL Server返回最后一个标识值的三个函数:IDENT_CURRENT.@@IDENTITY.SCOPE_IDENTITY,在些作个标记和小结. 其实MSDN对此有官方解释:这三个函数都返回最后生成的标识值. 但是,上述每个函数中定义的"最后"的作用域和会话有所不同. 1.IDENT_CURRENT 返回为某个会话和当前作用域中的指定表生成的最新标识值. 如果 IDENT_CURRENT 值为 NULL(因为表从未包含行或已被截断),IDENT_CURRENT

SQL Server表中添加新列并添加描述_MsSql

注: sql server 2005 及以上支持. 版本估计是不支持(工作环境2005,2008). 工作需要, 需要向SQL Server 现有表中添加新列并添加描述. 从而有个如下存储过程. (先附上存储过程然后解释) /********调用方法********** 作用: 添加列并添加列描述信息 调用: exec [SetColumnInfo] '表名', '列名', N'列说明,描述','列类型{默认:NVARCHAR(50)}','列默认值{默认:NULL}' ************

SQL Server表中添加新列并添加描述

注: sql server 2005 及以上支持. 版本估计是不支持(工作环境2005,2008). 工作需要, 需要向SQL Server 现有表中添加新列并添加描述. 从而有个如下存储过程. (先附上存储过程然后解释) /********调用方法********** 作用: 添加列并添加列描述信息 调用: exec [SetColumnInfo] '表名', '列名', N'列说明,描述','列类型{默认:NVARCHAR(50)}','列默认值{默认:NULL}' ************