優化SQLServer--表和索引的分區(二)

簡介數據庫

    以前一篇簡單的介紹了語法和一些基本的概念,隔了一段時間,以爲有必要細緻的經過實例來總結一下這部份內容。如以前所說,分區就是講大型的對象(表)分紅更小的塊來管理,基本單位是行。這也就產生了很大優點, 好比在數據庫維護備份還原操做的時候,好比在大量用戶訪問能致使死鎖的時候等等。架構

接下來咱們經過大量實例從分區到展現分區的效果以及一些實際案例來提升對這部分知識的理解。併發

--****************** --1.建立分區函數             --******************app

--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             GOspa

這裏咱們創建6個文件組,同時也能夠爲文件組建立文件,對象

建立好的文件和文件組文件

接下來我爲文件組建立分區方案:

 

--******************           --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

查詢結果如圖:

分區表

能夠發現按照日期的分佈產生了不一樣文件組的數據插入到了不一樣的文件裏面和索引裏面了。

接下來咱們經過分區切換來更好的理解分區的意義,首先要創建新的文件組(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中變爲了空。

image

若是須要切換回來執行

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)運行工做負載來提供是否分區的建議。

相關文章
相關標籤/搜索