优化SQLServer——表和分区索引(二)

时间:2023-02-20 20:26:57

简介

    之前一篇简单的介绍了语法和一些基本的概念,隔了一段时间,觉得有必要细致的通过实例来总结一下这部分内容。如之前所说,分区就是讲大型的对象(表)分成更小的块来管理,基本单位是行。这也就产生了很大优势, 比如在数据库维护备份还原操作的时候,比如在大量用户访问能导致死锁的时候等等。

接下来我们通过大量实例从分区到展示分区的效果以及一些实际案例来提高对这部分知识的理解。

--******************
--1.创建分区函数
--******************

--Create the partition function: dailyPF
DECLARE @StartDay DATE=DATEADD(dd,-3,CAST(SYSDATETIME() AS DATE));
CREATE PARTITION FUNCTION DailyPF (DATETIME2(0))
    AS RANGE RIGHT FOR VALUES
    (@StartDay, DATEADD(dd,1,@StartDay), DATEADD(dd,2,@StartDay), 
        DATEADD(dd,3,@StartDay), DATEADD(dd,4,@StartDay) );
GO

范围分区函数指定范围的边界,left和right关键字指定当数据库引擎按照剩余从左到右对区间值进行排序是,边界值属于那一边,默认为left。分区范围不能有间隔。

--******************
--2. 创建文件组

--******************

ALTER DATABASE PartitionThis ADD FILEGROUP DailyFG1
GO
ALTER DATABASE PartitionThis ADD FILEGROUP DailyFG2
GO
ALTER DATABASE PartitionThis ADD FILEGROUP DailyFG3
GO
ALTER DATABASE PartitionThis ADD FILEGROUP DailyFG4
GO
ALTER DATABASE PartitionThis ADD FILEGROUP DailyFG5
GO
ALTER DATABASE PartitionThis ADD FILEGROUP DailyFG6
GO

这里我们建立6个文件组,同时也可以为文件组创建文件,

优化SQLServer——表和分区索引(二)优化SQLServer——表和分区索引(二)

接下来我为文件组创建分区方案:

 

--******************
--3. 创建分区架构
--******************

--
CREATE PARTITION SCHEME DailyPS
    AS PARTITION DailyPF
    TO (DailyFG1, DailyFG2, DailyFG3, DailyFG4, DailyFG5, DailyFG6);

 

--******************
--4. 在分区架构上建表
--******************

if OBJECT_ID('OrdersDaily','U') is null
CREATE TABLE OrdersDaily (
    OrderDate DATETIME2(0) NOT NULL,
    OrderId int IDENTITY NOT NULL,
    OrderName nvarchar(256) NOT NULL
) on DailyPS(OrderDate)
GO

这里我们将分区函数映射到单个文件组里面,调用我们之前建立的分区函数即可。然后接着创建表在分区文件上,同时应用分区函数在

OrderDate时间上。这里我们还需要插入一部分测试数据便于观察,同时创建一个架构便于查询分区

--*******************************
--创建架构
--*******************************

--Create a schema for "partition helper" objects
CREATE SCHEMA [ph] AUTHORIZATION dbo;
GO

--插入测试数据
INSERT OrdersDaily(OrderDate, OrderName)
SELECT DATEADD(ss, t.N, DATEADD(dd,-3,CAST(CAST(SYSDATETIME() AS DATE) AS DATETIME2(0)))) AS OrderDate,
    CASE WHEN t.N % 3 = 0 THEN 'Robot' WHEN t.N % 4 = 0 THEN 'Badger'  ELSE 'Pen' END AS OrderName
FROM ph.tally AS t--tally是一个1到10万自增长的表,只有一个字段 N

WHERE N < = 1000;
   

INSERT OrdersDaily(OrderDate, OrderName)
SELECT DATEADD(ss, t.N, DATEADD(dd,-2,CAST(CAST(SYSDATETIME() AS DATE) AS DATETIME2(0)))) AS OrderDate,
    CASE WHEN t.N % 3 = 0 THEN 'Flying Monkey' WHEN t.N % 4 = 0 THEN 'Junebug'  ELSE 'Pen' END AS OrderName
FROM ph.tally AS t
WHERE N < = 2000;

INSERT OrdersDaily(OrderDate, OrderName)
SELECT DATEADD(ss, t.N, DATEADD(dd,-1,CAST(CAST(SYSDATETIME() AS DATE) AS DATETIME2(0)))) AS OrderDate,
    CASE WHEN t.N % 2 = 0 THEN 'Turtle' WHEN t.N % 5 = 0 THEN 'Eraser'  ELSE 'Pen' END AS OrderName
FROM ph.tally AS t
WHERE N < = 3000;

INSERT OrdersDaily(OrderDate, OrderName)
SELECT DATEADD(ss, t.N, CAST(CAST(SYSDATETIME() AS DATE) AS DATETIME2(0))) AS OrderDate,
    CASE WHEN t.N % 3 = 0 THEN 'Lasso' WHEN t.N % 2 = 0 THEN 'Cattle Prod'  ELSE 'Pen' END AS OrderName
FROM ph.tally AS t
WHERE N < = 4000;
GO

随即在创建相关的索引

--******************
--7. 创建索引
--******************
--添加聚集索引
ALTER TABLE OrdersDaily
ADD CONSTRAINT PKOrdersDaily
    PRIMARY KEY CLUSTERED(OrderDate,OrderId)
GO

--对齐索引
--
CREATE NONCLUSTERED INDEX NCOrderIdOrdersDaily
    ON OrdersDaily(OrderId)
GO

--非对齐索引
CREATE NONCLUSTERED INDEX NCOrderNameOrdersDailyNonAligned
    ON OrdersDaily(OrderName) ON [PRIMARY]
GO

此时建立分区文件数据等条件后,我们可以看一下相应的文件及数据的情况,可以同过如下DMV来查看

SELECT  SCHEMA_NAME(so.schema_id) AS schema_name ,
        OBJECT_NAME(p.object_id) AS object_name ,
        p.partition_number ,
        p.data_compression_desc ,
        dbps.row_count ,
        dbps.reserved_page_count * 8 / 1024. AS reserved_mb ,
        si.index_id ,
        CASE WHEN si.index_id = 0 THEN '(heap!)'
                ELSE si.name
        END AS index_name ,
        si.is_unique ,
        si.data_space_id ,
        mappedto.name AS mapped_to_name ,
        mappedto.type_desc AS mapped_to_type_desc ,
        partitionds.name AS partition_filegroup ,
        pf.name AS pf_name ,
        pf.type_desc AS pf_type_desc ,
        pf.fanout AS pf_fanout ,
        pf.boundary_value_on_right ,
        ps.name AS partition_scheme_name ,
        rv.value AS range_value
FROM    sys.partitions p
JOIN    sys.objects so
        ON p.object_id = so.object_id
            AND so.is_ms_shipped = 0
LEFT JOIN sys.dm_db_partition_stats AS dbps
        ON p.object_id = dbps.object_id
            AND p.partition_id = dbps.partition_id
JOIN    sys.indexes si
        ON p.object_id = si.object_id
            AND p.index_id = si.index_id
LEFT JOIN sys.data_spaces mappedto
        ON si.data_space_id = mappedto.data_space_id
LEFT JOIN sys.destination_data_spaces dds
        ON si.data_space_id = dds.partition_scheme_id
            AND p.partition_number = dds.destination_id
LEFT JOIN sys.data_spaces partitionds
        ON dds.data_space_id = partitionds.data_space_id
LEFT JOIN sys.partition_schemes AS ps
        ON dds.partition_scheme_id = ps.data_space_id
LEFT JOIN sys.partition_functions AS pf
        ON ps.function_id = pf.function_id
LEFT JOIN sys.partition_range_values AS rv
        ON pf.function_id = rv.function_id
            AND dds.destination_id = CASE pf.boundary_value_on_right
                                        WHEN 0 THEN rv.boundary_id
                                        ELSE rv.boundary_id + 1
                                    END

查询结果如图:

优化SQLServer——表和分区索引(二)

可以发现按照日期的分布产生了不同文件组的数据插入到了不同的文件里面和索引里面了。

接下来我们通过分区切换来更好的理解分区的意义,首先要建立新的文件组(DailyF7)来切换分区,同时创建一个分区表OrdersDailyLoad,并向这个表里面插入5000条数据创建索引等以上的操作单独对此表进行一遍重复操作,来实现对新分区的新标的对齐。注意5000条数据一定要在指定范围内,比如使用check约束使数据在11.30-12.1日内的数据。

 

代码:

在切换之前我们一定要禁用或者删除掉这个分区的对其的索引
ALTER INDEX NCOrderNameOrdersDailyNonAligned ON OrdersDaily DISABLE;
GO
ALTER TABLE OrdersDailyLoad
SWITCH TO OrdersDaily PARTITION 6;
GO

如图,分区切换后文件组6中变为了5000条数据,而7中变为了空。

优化SQLServer——表和分区索引(二)

如果需要切换回来执行

ALTER TABLE PARTITION 6
SWITCH TO OrdersDaily OrdersDailyLoad ;
GO

如果需要合并分区

ALTER PARTITION FUNCTION DailyPF ()
        MERGE RANGE (‘2015-11-27 00:00:00.000’)

结果:此界点两个分区将合并为一个

 

 

 

总结:

           通过以上代码和实例的展示,我们能了解如何使用分区。同时我们要知道分区的意义。但是要知道分区也是一把双刃剑,它可以看做是一个性能选项、管理选项、可扩展工具,在提高数据查询、维护性能的同时也对数据库的备份还原策略、索引的维护、并发性以及变分区锁等有副作用,所以具体是否选用表分区要根据实际情况来判断,然后推荐一个工具(DataBase Tuning Adcisor)运行工作负载来提供是否分区的建议。

优化SQLServer——表和分区索引(二)的更多相关文章

  1. 优化SQLServer——表和分区索引

    概念: 简单地说,分区是将大型的对象(如表)分成更小的且易于管理的小块.分区的基本单位是行,需要注意的是与分区视图不同的地方时,分区必须位于同一个数据库内. 分区的原因:            对于非 ...

  2. MySQL单机优化---分表、分区、分库

    一.分表: 水平分表:根据条件把数据分为N个表(例如:商品表中有月份列,则可以按月份进行水平分表). 使用场景:一张表中数据太多,查询效率太慢. 当需要同时查询被水平分表的多张表时: 在两条SQL语句 ...

  3. SQL Server查询性能优化——堆表、碎片与索引(二)

    本文是对 SQL Server查询性能优化——堆表.碎片与索引(一)的一些总结.  第一:先对 SQL Server查询性能优化——堆表.碎片与索引(一)中的例一的SET STATISTICS IO之 ...

  4. &lpar;转&rpar;SQLSERVER表分区的介绍&lpar;一&rpar;

    下面进入正题吧,很多时候当单张数据表的数据量比较大的时候比如千万级别条记录.上亿级别记录,如果不做优化,那么查询的效率大家清楚. 有经验的人会通过各种手段做优化,其中表分区就是其中一种手段. 个人对表 ...

  5. sqlserver表分区

    参考:http://www.cnblogs.com/knowledgesea/p/3696912.html 及百度搜索sqlserver表分区 create partition function sg ...

  6. SQL优化的四个方面,缓存,表结构,索引,SQL语句

    一,缓存 数据库属于 IO 密集型的应用程序,其主要职责就是数据的管理及存储工作.而我们知道,从内存中读取一个数据库的时间是微秒级别,而从一块普通硬盘上读取一个IO是在毫秒级别,二者相差3个数量级.所 ...

  7. 优化的四个方面,缓存,表结构,索引,SQL语句

    一,缓存 数据库属于 IO 密集型的应用程序,其主要职责就是数据的管理及存储工作.而我们知道,从内存中读取一个数据库的时间是微秒级别,而从一块普通硬盘上读取一个IO是在毫秒级别,二者相差3个数量级.所 ...

  8. MySQL数据库性能优化:表、索引、SQL等

    一.MySQL 数据库性能优化之SQL优化 注:这篇文章是以 MySQL 为背景,很多内容同时适用于其他关系型数据库,需要有一些索引知识为基础 优化目标 减少 IO 次数IO永远是数据库最容易瓶颈的地 ...

  9. sqlserver表分区小结

    为什么要表分区?  当一个表的数据量太大的时候,我们最想做的一件事是什么?将这个表一分为二或者更多分,但是表还是这个表,只是将其内容存储分开,这样读取就快了N倍了 原理:表数据是无法放在文件中的,但是 ...

随机推荐

  1. Squire – 简洁的 HTML5 富文本编辑器

    Squire 是一个简洁的 HTML5 富文本编辑器,它提供了强大的跨浏览器的标准化,超级轻巧灵活.它是建立在现在和未来并作为研究,因此并不支持那些古老的浏览器. 在线演示      源码下载 您可能 ...

  2. settimeout,cleartimeout的使用分析

    设置时间的定时轮回执行,大家想到的js也就是settimeout这个方法,这个方法确实能够实现定时反复执行的功能,clearttimeout这是清理或者是暂停轮回执行的情况.可是发现clearttim ...

  3. iOS开发:插件记录

    进入沙盒的插件 https://github.com/TongeJie/ZLGotoSandboxPlugin 图片提示的插件 https://github.com/ksuther/KSImageNa ...

  4. 分享一段H264视频和AAC音频的RTP封包代码

    1. H264视频的RTP封包 static int h264_parse(Track *tr, uint8_t *data, size_t len) { h264_priv *priv = tr-& ...

  5. Storm源码分析--Nimbus-data

    nimbus-datastorm-core/backtype/storm/nimbus.clj (defn nimbus-data [conf inimbus] (let [forced-schedu ...

  6. AI繁荣下的隐忧——Google Tensorflow安全风险剖析

    本文由云+社区发表 作者:[ Tencent Blade Team ] Cradmin 我们身处一个巨变的时代,各种新技术层出不穷,人工智能作为一个诞生于上世纪50年代的概念,近两年出现井喷式发展,得 ...

  7. CLR 协变、逆变

    看书看得有点晕了,协变.逆变傻傻分不清楚. 看到泛型和委托.委托方法,发现这里面的协变和逆变不一样. 泛型的逆变和协变:如果某个返回类型可以由其基类替换,那么这个类型就是支持协变的.如果某个参数类型可 ...

  8. 潭州课堂25班:Ph201805201 WEB 之 HTML 第一课 &lpar;课堂笔记&rpar;

    什么是HTML 超文本标记语言(HyperText Markup Language,简称 HTML) HTML 是一门标记语言,标记语言由一套标记标签组成, 学习 HTML,其实就是学习标签 HTML ...

  9. POJ 2785 4 Values whose Sum is 0(暴力枚举的优化策略)

    题目链接: https://cn.vjudge.net/problem/POJ-2785 The SUM problem can be formulated as follows: given fou ...

  10. EBS中比较复杂的trace方法

    FND LOG Messages-------------------------a) Using the System Administrator Responsibility, navigate  ...