簡介數據庫
以前一篇簡單的介紹了語法和一些基本的概念,隔了一段時間,以爲有必要細緻的經過實例來總結一下這部份內容。如以前所說,分區就是講大型的對象(表)分紅更小的塊來管理,基本單位是行。這也就產生了很大優點, 好比在數據庫維護備份還原操做的時候,好比在大量用戶訪問能致使死鎖的時候等等。架構
接下來咱們經過大量實例從分區到展現分區的效果以及一些實際案例來提升對這部分知識的理解。併發
--****************** --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中變爲了空。
若是須要切換回來執行
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)運行工做負載來提供是否分區的建議。