再說一下表分區


再說一下表分區

網上表分區的文章成千上萬,但是分區之后表數據的分布和流向都沒有說

首先要說明的是表分區的分區不是指頁面存儲概念的分區,我用下面的圖來表示

他們是沒有關系的


正式開始

SQL腳本如下:

 1 USE master
 2 GO
 3 
 4 --創建數據庫
 5 CREATE DATABASE [Test]
 6 GO
 7 
 8 USE [Test]
 9 GO
10 
11 
12 --1.創建文件組
13 ALTER DATABASE [Test]
14 ADD FILEGROUP [FG_TestUnique_Id_01]
15 
16 ALTER DATABASE [Test]
17 ADD FILEGROUP [FG_TestUnique_Id_02]
18 
19 ALTER DATABASE [Test]
20 ADD FILEGROUP [FG_TestUnique_Id_03]
21 
22 --2.創建文件
23 ALTER DATABASE [Test]
24 ADD FILE
25 (NAME = N'FG_TestUnique_Id_01_data',FILENAME = N'E:\FG_TestUnique_Id_01_data.ndf',SIZE = 1MB, FILEGROWTH = 1MB )
26 TO FILEGROUP [FG_TestUnique_Id_01];
27 
28 ALTER DATABASE [Test]
29 ADD FILE
30 (NAME = N'FG_TestUnique_Id_02_data',FILENAME = N'E:\FG_TestUnique_Id_02_data.ndf',SIZE = 1MB, FILEGROWTH = 1MB )
31 TO FILEGROUP [FG_TestUnique_Id_02];
32 
33 ALTER DATABASE [Test]
34 ADD FILE
35 (NAME = N'FG_TestUnique_Id_03_data',FILENAME = N'E:\FG_TestUnique_Id_03_data.ndf',SIZE = 1MB, FILEGROWTH = 1MB )
36 TO FILEGROUP [FG_TestUnique_Id_03];

創建分區函數和分區方案
我們創建了一個用於數據類型為int的分區函數,按照數值來划分
文件組                            分區       取值范圍
[FG_TestUnique_Id_01]    1        (小於2, 2]  --包括2
[FG_TestUnique_Id_02]    2        [3, 4]
[FG_TestUnique_Id_03]    3        (4,大於4)  --不包括4

 1 --3.創建分區函數
 2 --我們創建了一個用於數據類型為int的分區函數,按照數值來划分
 3 --文件組                  分區      取值范圍
 4 --[FG_TestUnique_Id_01]    1        (小於2, 2]--包括2
 5 --[FG_TestUnique_Id_02]    2        [3, 4]
 6 --[FG_TestUnique_Id_03]    3        (4,大於4)  --不包括4
 7 
 8 CREATE PARTITION FUNCTION
 9 Fun_TestUnique_Id(INT) AS
10 RANGE LEFT
11 FOR VALUES(2,4)
12 
13 
14 
15 
16 --4.創建分區方案
17 CREATE PARTITION SCHEME
18 Sch_TestUnique_Id AS
19 PARTITION Fun_TestUnique_Id
20 TO([FG_TestUnique_Id_01],[FG_TestUnique_Id_02],[FG_TestUnique_Id_03])

建立分區表

 1 --5.創建分區表
 2 CREATE TABLE testPartionTable
 3 (
 4   id INT  NOT NULL,
 5   itemno CHAR(20),
 6   itemname CHAR(40)
 7 )ON Sch_TestUnique_Id([id])
 8 
 9 
10 INSERT INTO [dbo].[testPartionTable] ( [id], [itemno], [itemname] )
11 SELECT 1,'1','中國' UNION ALL
12 SELECT 2,'2','法國' UNION ALL
13 SELECT 3,'3','美國' UNION ALL
14 SELECT 4,'4','英國' UNION ALL
15 SELECT 5,'5','德國'

查看邊界值點

1 --查看邊界值點
2 select * from sys.partition_range_values
3 GO

 

查看表數據

1 SELECT * FROM [dbo].[testNonPartionTable]
2 GO

 

我們看一下當前數據庫的情況

1 EXEC [sys].[sp_helpdb] @dbname = test -- sysname
2 GO

FG_TestUnique_Id_0X這三個文件組建立在三個ndf文件上,三個ndf文件都位於E盤

而fileid分別是3、4、5


我們看一下表的頁面分配情況

 1 CREATE TABLE DBCCResult (
 2 PageFID NVARCHAR(200),
 3 PagePID NVARCHAR(200),
 4 IAMFID NVARCHAR(200),
 5 IAMPID NVARCHAR(200),
 6 ObjectID NVARCHAR(200),
 7 IndexID NVARCHAR(200),
 8 PartitionNumber NVARCHAR(200),
 9 PartitionID NVARCHAR(200),
10 iam_chain_type NVARCHAR(200),
11 PageType NVARCHAR(200),
12 IndexLevel NVARCHAR(200),
13 NextPageFID NVARCHAR(200),
14 NextPagePID NVARCHAR(200),
15 PrevPageFID NVARCHAR(200),
16 PrevPagePID NVARCHAR(200)
17 )
18 
19 --TRUNCATE TABLE [dbo].[DBCCResult]
20 INSERT INTO DBCCResult EXEC ('DBCC IND(test,testPartionTable,-1) ')
21 
22 SELECT * FROM [dbo].[DBCCResult] ORDER BY [PageType] DESC 
View Code

 

1 SELECT  *
2 FROM    sys.dm_db_index_physical_stats(DB_ID('test'),
3                                        OBJECT_ID('testPartionTable'), NULL,
4                                        NULL, 'detailed')

從上面兩個圖我們可以得知

-----------------------------------------------------------------------------------------------------------------

-------------------------------------------------------------------------------------------------------------

 

分區號1~3對應的文件組名和ndf文件名分別是:

分區號1 (PartitionNumber1)-》文件組FG_TestUnique_Id_01-》E:\FG_TestUnique_Id_01_data.ndf

分區號2 (PartitionNumber2)-》文件組FG_TestUnique_Id_02-》E:\FG_TestUnique_Id_02_data.ndf

分區號3 (PartitionNumber3)-》文件組FG_TestUnique_Id_03-》E:\FG_TestUnique_Id_03_data.ndf

 

表中只有一個數據頁面8 和一個IAM頁面9

但是每個ndf文件里面卻都存儲了一份數據頁面8 和一份IAM頁面9

而且每個ndf文件里面 數據頁面存儲的內容都不一樣,雖然頁面編號一樣,都是8


數據頁面存儲的內容

我們來看一下每個ndf文件里面的數據頁面都存儲了些什么內容?

我們先來看一下testPartionTable表的objectID

1 SELECT OBJECT_ID('testPartionTable') AS 'OBJECTID'

 

先看FILEID為3的文件里面的數據頁面

1 DBCC TRACEON(3604,-1)
2 GO
3 DBCC PAGE(test,3,8,3)
4 GO
 1 DBCC 執行完畢。如果 DBCC 輸出了錯誤信息,請與系統管理員聯系。
 2 
 3 PAGE: (3:8)
 4 
 5 
 6 BUFFER:
 7 
 8 
 9 BUF @0x03DFDE90
10 
11 bpage = 0x16EEE000                   bhash = 0x00000000                   bpageno = (3:8)
12 bdbid = 11                           breferences = 0                      bUse1 = 28337
13 bstat = 0x3c0000b                    blog = 0x212121bb                    bnext = 0x00000000
14 
15 PAGE HEADER:
16 
17 
18 Page @0x16EEE000
19 
20 m_pageId = (3:8)                     m_headerVersion = 1                  m_type = 1
21 m_typeFlagBits = 0x4                 m_level = 0                          m_flagBits = 0x8000
22 m_objId (AllocUnitId.idObj) = 82     m_indexId (AllocUnitId.idInd) = 256  
23 Metadata: AllocUnitId = 72057594043301888                                 
24 Metadata: PartitionId = 72057594038321152                                 Metadata: IndexId = 0
25 Metadata: ObjectId = 2073058421      m_prevPage = (0:0)                   m_nextPage = (0:0)
26 pminlen = 68                         m_slotCnt = 2                        m_freeCnt = 7950
27 m_freeData = 238                     m_reservedCnt = 0                    m_lsn = (41:289:25)
28 m_xactReserved = 0                   m_xdesId = (0:0)                     m_ghostRecCnt = 0
29 m_tornBits = 0                       
30 
31 Allocation Status
32 
33 GAM (3:2) = ALLOCATED                SGAM (3:3) = ALLOCATED               
34 PFS (3:1) = 0x61 MIXED_EXT ALLOCATED  50_PCT_FULL                         DIFF (3:6) = CHANGED
35 ML (3:7) = NOT MIN_LOGGED            
36 
37 Slot 0 Offset 0x60 Length 71
38 
39 Record Type = PRIMARY_RECORD         Record Attributes =  NULL_BITMAP     
40 Memory Dump @0x0A70C060
41 
42 00000000:   10004400 01000000 31202020 20202020 †..D.....1                
43 00000010:   20202020 20202020 20202020 d6d0b9fa †            ....         
44 00000020:   20202020 20202020 20202020 2020202045 00000030:   20202020 20202020 20202020 2020202046 00000040:   20202020 0300f8††††††††††††††††††††††    ...                  
47 
48 Slot 0 Column 0 Offset 0x4 Length 4
49 
50 id = 1                               
51 
52 Slot 0 Column 1 Offset 0x8 Length 20
53 
54 itemno = 1                           
55 
56 Slot 0 Column 2 Offset 0x1c Length 40
57 
58 itemname = 中國                                                           
59 
60 Slot 1 Offset 0xa7 Length 71
61 
62 Record Type = PRIMARY_RECORD         Record Attributes =  NULL_BITMAP     
63 Memory Dump @0x0A70C0A7
64 
65 00000000:   10004400 02000000 32202020 20202020 †..D.....2                
66 00000010:   20202020 20202020 20202020 b7a8b9fa †            ....         
67 00000020:   20202020 20202020 20202020 2020202068 00000030:   20202020 20202020 20202020 2020202069 00000040:   20202020 0300f8††††††††††††††††††††††    ...                  
70 
71 Slot 1 Column 0 Offset 0x4 Length 4
72 
73 id = 2                               
74 
75 Slot 1 Column 1 Offset 0x8 Length 20
76 
77 itemno = 2                           
78 
79 Slot 1 Column 2 Offset 0x1c Length 40
80 
81 itemname = 法國                                                           
82 
83 
84 DBCC 執行完畢。如果 DBCC 輸出了錯誤信息,請與系統管理員聯系。
View Code

這個頁面是屬於testPartionTable表

 1 Slot 0 Column 0 Offset 0x4 Length 4
 2 
 3 id = 1                               
 4 
 5 Slot 0 Column 1 Offset 0x8 Length 20
 6 
 7 itemno = 1                           
 8 
 9 Slot 0 Column 2 Offset 0x1c Length 40
10 
11 itemname = 中國                                                           
12 
13 Slot 1 Offset 0xa7 Length 71
14 
15               
16 
17 Slot 1 Column 0 Offset 0x4 Length 4
18 
19 id = 2                               
20 
21 Slot 1 Column 1 Offset 0x8 Length 20
22 
23 itemno = 2                           
24 
25 Slot 1 Column 2 Offset 0x1c Length 40
26 
27 itemname = 法國         

FILEID為3的文件里面的數據頁面里存放了id為1和id為2的這兩條記錄

 

看FILEID為4的文件里面的數據頁面

1 DBCC TRACEON(3604,-1)
2 GO
3 DBCC PAGE(test,4,8,3)
4 GO
 1 DBCC 執行完畢。如果 DBCC 輸出了錯誤信息,請與系統管理員聯系。
 2 
 3 PAGE: (4:8)
 4 
 5 
 6 BUFFER:
 7 
 8 
 9 BUF @0x03E6777C
10 
11 bpage = 0x19A78000                   bhash = 0x00000000                   bpageno = (4:8)
12 bdbid = 11                           breferences = 0                      bUse1 = 28520
13 bstat = 0x3c0000b                    blog = 0x212121bb                    bnext = 0x00000000
14 
15 PAGE HEADER:
16 
17 
18 Page @0x19A78000
19 
20 m_pageId = (4:8)                     m_headerVersion = 1                  m_type = 1
21 m_typeFlagBits = 0x4                 m_level = 0                          m_flagBits = 0x8000
22 m_objId (AllocUnitId.idObj) = 83     m_indexId (AllocUnitId.idInd) = 256  
23 Metadata: AllocUnitId = 72057594043367424                                 
24 Metadata: PartitionId = 72057594038386688                                 Metadata: IndexId = 0
25 Metadata: ObjectId = 2073058421      m_prevPage = (0:0)                   m_nextPage = (0:0)
26 pminlen = 68                         m_slotCnt = 2                        m_freeCnt = 7950
27 m_freeData = 238                     m_reservedCnt = 0                    m_lsn = (41:289:49)
28 m_xactReserved = 0                   m_xdesId = (0:0)                     m_ghostRecCnt = 0
29 m_tornBits = 0                       
30 
31 Allocation Status
32 
33 GAM (4:2) = ALLOCATED                SGAM (4:3) = ALLOCATED               
34 PFS (4:1) = 0x61 MIXED_EXT ALLOCATED  50_PCT_FULL                         DIFF (4:6) = CHANGED
35 ML (4:7) = NOT MIN_LOGGED            
36 
37 Slot 0 Offset 0x60 Length 71
38 
39 Record Type = PRIMARY_RECORD         Record Attributes =  NULL_BITMAP     
40 Memory Dump @0x0A37C060
41 
42 00000000:   10004400 03000000 33202020 20202020 †..D.....3                
43 00000010:   20202020 20202020 20202020 c3c0b9fa †            ....         
44 00000020:   20202020 20202020 20202020 2020202045 00000030:   20202020 20202020 20202020 2020202046 00000040:   20202020 0300f8††††††††††††††††††††††    ...                  
47 
48 Slot 0 Column 0 Offset 0x4 Length 4
49 
50 id = 3                               
51 
52 Slot 0 Column 1 Offset 0x8 Length 20
53 
54 itemno = 3                           
55 
56 Slot 0 Column 2 Offset 0x1c Length 40
57 
58 itemname = 美國                                                           
59 
60 Slot 1 Offset 0xa7 Length 71
61 
62 Record Type = PRIMARY_RECORD         Record Attributes =  NULL_BITMAP     
63 Memory Dump @0x0A37C0A7
64 
65 00000000:   10004400 04000000 34202020 20202020 †..D.....4                
66 00000010:   20202020 20202020 20202020 d3a2b9fa †            ....         
67 00000020:   20202020 20202020 20202020 2020202068 00000030:   20202020 20202020 20202020 2020202069 00000040:   20202020 0300f8††††††††††††††††††††††    ...                  
70 
71 Slot 1 Column 0 Offset 0x4 Length 4
72 
73 id = 4                               
74 
75 Slot 1 Column 1 Offset 0x8 Length 20
76 
77 itemno = 4                           
78 
79 Slot 1 Column 2 Offset 0x1c Length 40
80 
81 itemname = 英國                                                           
82 
83 
84 DBCC 執行完畢。如果 DBCC 輸出了錯誤信息,請與系統管理員聯系。
View Code

 這個頁面是屬於testPartionTable表

 1 Slot 0 Offset 0x60 Length 71
 2 
 3 
 4 Slot 0 Column 0 Offset 0x4 Length 4
 5 
 6 id = 3                               
 7 
 8 Slot 0 Column 1 Offset 0x8 Length 20
 9 
10 itemno = 3                           
11 
12 Slot 0 Column 2 Offset 0x1c Length 40
13 
14 itemname = 美國                                                           
15 
16 Slot 1 Offset 0xa7 Length 71
17 
18 
19 Slot 1 Column 0 Offset 0x4 Length 4
20 
21 id = 4                               
22 
23 Slot 1 Column 1 Offset 0x8 Length 20
24 
25 itemno = 4                           
26 
27 Slot 1 Column 2 Offset 0x1c Length 40
28 
29 itemname = 英國         

FILEID為4的文件里面的數據頁面里存放了id為3和id為4的這兩條記錄

 

看FILEID為5的文件里面的數據頁面

1 DBCC TRACEON(3604,-1)
2 GO
3 DBCC PAGE(test,5,8,3)
4 GO

 這個頁面是屬於testPartionTable表

 1 DBCC 執行完畢。如果 DBCC 輸出了錯誤信息,請與系統管理員聯系。
 2 
 3 PAGE: (5:8)
 4 
 5 
 6 BUFFER:
 7 
 8 
 9 BUF @0x03E7B0FC
10 
11 bpage = 0x1A2A8000                   bhash = 0x00000000                   bpageno = (5:8)
12 bdbid = 11                           breferences = 0                      bUse1 = 28674
13 bstat = 0x3c0000b                    blog = 0x212121bb                    bnext = 0x00000000
14 
15 PAGE HEADER:
16 
17 
18 Page @0x1A2A8000
19 
20 m_pageId = (5:8)                     m_headerVersion = 1                  m_type = 1
21 m_typeFlagBits = 0x4                 m_level = 0                          m_flagBits = 0x8000
22 m_objId (AllocUnitId.idObj) = 84     m_indexId (AllocUnitId.idInd) = 256  
23 Metadata: AllocUnitId = 72057594043432960                                 
24 Metadata: PartitionId = 72057594038452224                                 Metadata: IndexId = 0
25 Metadata: ObjectId = 2073058421      m_prevPage = (0:0)                   m_nextPage = (0:0)
26 pminlen = 68                         m_slotCnt = 1                        m_freeCnt = 8023
27 m_freeData = 167                     m_reservedCnt = 0                    m_lsn = (41:326:23)
28 m_xactReserved = 0                   m_xdesId = (0:0)                     m_ghostRecCnt = 0
29 m_tornBits = 0                       
30 
31 Allocation Status
32 
33 GAM (5:2) = ALLOCATED                SGAM (5:3) = ALLOCATED               
34 PFS (5:1) = 0x61 MIXED_EXT ALLOCATED  50_PCT_FULL                         DIFF (5:6) = CHANGED
35 ML (5:7) = NOT MIN_LOGGED            
36 
37 Slot 0 Offset 0x60 Length 71
38 
39 Record Type = PRIMARY_RECORD         Record Attributes =  NULL_BITMAP     
40 Memory Dump @0x0A37C060
41 
42 00000000:   10004400 05000000 35202020 20202020 †..D.....5                
43 00000010:   20202020 20202020 20202020 b5c2b9fa †            ....         
44 00000020:   20202020 20202020 20202020 2020202045 00000030:   20202020 20202020 20202020 2020202046 00000040:   20202020 0300f8††††††††††††††††††††††    ...                  
47 
48 Slot 0 Column 0 Offset 0x4 Length 4
49 
50 id = 5                               
51 
52 Slot 0 Column 1 Offset 0x8 Length 20
53 
54 itemno = 5                           
55 
56 Slot 0 Column 2 Offset 0x1c Length 40
57 
58 itemname = 德國                                                           
59 
60 
61 DBCC 執行完畢。如果 DBCC 輸出了錯誤信息,請與系統管理員聯系。
View Code
 1 Slot 0 Offset 0x60 Length 71
 2 
 3 
 4 Slot 0 Column 0 Offset 0x4 Length 4
 5 
 6 id = 5                               
 7 
 8 Slot 0 Column 1 Offset 0x8 Length 20
 9 
10 itemno = 5                           
11 
12 Slot 0 Column 2 Offset 0x1c Length 40
13 
14 itemname = 德國

FILEID為5的文件里面的數據頁面里存放了id為5這條記錄

 

再看我們剛才建立的分區函數,和各個ndf里的數據頁面存儲的記錄條數

 1 創建分區函數
 2 我們創建了一個用於數據類型為int的分區函數,按照數值來划分
 3 文件組                  分區      取值范圍
 4 [FG_TestUnique_Id_01]    1        (小於2, 2]--包括2
 5 [FG_TestUnique_Id_02]    2        [3, 4]
 6 [FG_TestUnique_Id_03]    3        (4,大於4)  --不包括4
 7 
 8 CREATE PARTITION FUNCTION
 9 Fun_TestUnique_Id(INT) AS
10 RANGE LEFT
11 FOR VALUES(2,4)          

 

當執行select * from testPartionTable的時候,就需要跨這三個ndf文件來讀取記錄

IO一定會有所影響,所以一般應用都是按照月份、性別等來進行分區,確保查詢數據的時候不要跨多個文件組


如果表沒有分區是怎樣的?
SQL腳本如下,建立testNonPartionTable表:

 1 USE [Test]
 2 GO
 3 CREATE TABLE testNonPartionTable
 4 (
 5   id INT  NOT NULL,
 6   itemno CHAR(20),
 7   itemname CHAR(40)
 8 )
 9 
10 
11 INSERT INTO [dbo].[testNonPartionTable] ( [id], [itemno], [itemname] )
12 SELECT 1,'1','中國' UNION ALL
13 SELECT 2,'2','法國' UNION ALL
14 SELECT 3,'3','美國' UNION ALL
15 SELECT 4,'4','英國' UNION ALL
16 SELECT 5,'5','德國'
17 
18 --TRUNCATE TABLE [dbo].[DBCCResult]
19 INSERT INTO DBCCResult EXEC ('DBCC IND(test,testNonPartionTable,-1) ')
20 
21 SELECT * FROM [dbo].[DBCCResult] ORDER BY [PageType] DESC 
View Code

1 DBCC TRACEON(3604,-1)
2 GO
3 DBCC PAGE(test,1,47,3)
4 GO
  1 DBCC 執行完畢。如果 DBCC 輸出了錯誤信息,請與系統管理員聯系。
  2 
  3 PAGE: (1:47)
  4 
  5 
  6 BUFFER:
  7 
  8 
  9 BUF @0x03E83C38
 10 
 11 bpage = 0x1763C000                   bhash = 0x00000000                   bpageno = (1:47)
 12 bdbid = 11                           breferences = 0                      bUse1 = 29165
 13 bstat = 0x3c0000b                    blog = 0xca2159bb                    bnext = 0x00000000
 14 
 15 PAGE HEADER:
 16 
 17 
 18 Page @0x1763C000
 19 
 20 m_pageId = (1:47)                    m_headerVersion = 1                  m_type = 1
 21 m_typeFlagBits = 0x4                 m_level = 0                          m_flagBits = 0x8000
 22 m_objId (AllocUnitId.idObj) = 86     m_indexId (AllocUnitId.idInd) = 256  
 23 Metadata: AllocUnitId = 72057594043564032                                 
 24 Metadata: PartitionId = 72057594038583296                                 Metadata: IndexId = 0
 25 Metadata: ObjectId = 2105058535      m_prevPage = (0:0)                   m_nextPage = (0:0)
 26 pminlen = 68                         m_slotCnt = 5                        m_freeCnt = 7731
 27 m_freeData = 451                     m_reservedCnt = 0                    m_lsn = (41:355:23)
 28 m_xactReserved = 0                   m_xdesId = (0:0)                     m_ghostRecCnt = 0
 29 m_tornBits = 0                       
 30 
 31 Allocation Status
 32 
 33 GAM (1:2) = ALLOCATED                SGAM (1:3) = NOT ALLOCATED           
 34 PFS (1:1) = 0x61 MIXED_EXT ALLOCATED  50_PCT_FULL                         DIFF (1:6) = CHANGED
 35 ML (1:7) = NOT MIN_LOGGED            
 36 
 37 Slot 0 Offset 0x60 Length 71
 38 
 39 Record Type = PRIMARY_RECORD         Record Attributes =  NULL_BITMAP     
 40 Memory Dump @0x0A37C060
 41 
 42 00000000:   10004400 01000000 31202020 20202020 †..D.....1                
 43 00000010:   20202020 20202020 20202020 d6d0b9fa †            ....         
 44 00000020:   20202020 20202020 20202020 20202020 45 00000030:   20202020 20202020 20202020 20202020 46 00000040:   20202020 0300f8††††††††††††††††††††††    ...                  
 47 
 48 Slot 0 Column 0 Offset 0x4 Length 4
 49 
 50 id = 1                               
 51 
 52 Slot 0 Column 1 Offset 0x8 Length 20
 53 
 54 itemno = 1                           
 55 
 56 Slot 0 Column 2 Offset 0x1c Length 40
 57 
 58 itemname = 中國                                                           
 59 
 60 Slot 1 Offset 0xa7 Length 71
 61 
 62 Record Type = PRIMARY_RECORD         Record Attributes =  NULL_BITMAP     
 63 Memory Dump @0x0A37C0A7
 64 
 65 00000000:   10004400 02000000 32202020 20202020 †..D.....2                
 66 00000010:   20202020 20202020 20202020 b7a8b9fa †            ....         
 67 00000020:   20202020 20202020 20202020 20202020 68 00000030:   20202020 20202020 20202020 20202020 69 00000040:   20202020 0300f8††††††††††††††††††††††    ...                  
 70 
 71 Slot 1 Column 0 Offset 0x4 Length 4
 72 
 73 id = 2                               
 74 
 75 Slot 1 Column 1 Offset 0x8 Length 20
 76 
 77 itemno = 2                           
 78 
 79 Slot 1 Column 2 Offset 0x1c Length 40
 80 
 81 itemname = 法國                                                           
 82 
 83 Slot 2 Offset 0xee Length 71
 84 
 85 Record Type = PRIMARY_RECORD         Record Attributes =  NULL_BITMAP     
 86 Memory Dump @0x0A37C0EE
 87 
 88 00000000:   10004400 03000000 33202020 20202020 †..D.....3                
 89 00000010:   20202020 20202020 20202020 c3c0b9fa †            ....         
 90 00000020:   20202020 20202020 20202020 20202020 91 00000030:   20202020 20202020 20202020 20202020 92 00000040:   20202020 0300f8††††††††††††††††††††††    ...                  
 93 
 94 Slot 2 Column 0 Offset 0x4 Length 4
 95 
 96 id = 3                               
 97 
 98 Slot 2 Column 1 Offset 0x8 Length 20
 99 
100 itemno = 3                           
101 
102 Slot 2 Column 2 Offset 0x1c Length 40
103 
104 itemname = 美國                                                           
105 
106 Slot 3 Offset 0x135 Length 71
107 
108 Record Type = PRIMARY_RECORD         Record Attributes =  NULL_BITMAP     
109 Memory Dump @0x0A37C135
110 
111 00000000:   10004400 04000000 34202020 20202020 †..D.....4                
112 00000010:   20202020 20202020 20202020 d3a2b9fa †            ....         
113 00000020:   20202020 20202020 20202020 20202020114 00000030:   20202020 20202020 20202020 20202020115 00000040:   20202020 0300f8††††††††††††††††††††††    ...                  
116 
117 Slot 3 Column 0 Offset 0x4 Length 4
118 
119 id = 4                               
120 
121 Slot 3 Column 1 Offset 0x8 Length 20
122 
123 itemno = 4                           
124 
125 Slot 3 Column 2 Offset 0x1c Length 40
126 
127 itemname = 英國                                                           
128 
129 Slot 4 Offset 0x17c Length 71
130 
131 Record Type = PRIMARY_RECORD         Record Attributes =  NULL_BITMAP     
132 Memory Dump @0x0A37C17C
133 
134 00000000:   10004400 05000000 35202020 20202020 †..D.....5                
135 00000010:   20202020 20202020 20202020 b5c2b9fa †            ....         
136 00000020:   20202020 20202020 20202020 20202020137 00000030:   20202020 20202020 20202020 20202020138 00000040:   20202020 0300f8††††††††††††††††††††††    ...                  
139 
140 Slot 4 Column 0 Offset 0x4 Length 4
141 
142 id = 5                               
143 
144 Slot 4 Column 1 Offset 0x8 Length 20
145 
146 itemno = 5                           
147 
148 Slot 4 Column 2 Offset 0x1c Length 40
149 
150 itemname = 德國                                                           
151 
152 
153 DBCC 執行完畢。如果 DBCC 輸出了錯誤信息,請與系統管理員聯系。
View Code

 

 1 itemname = 中國                                                           
 2 
 3 Slot 1 Offset 0xa7 Length 71
 4 
 5 
 6 Slot 1 Column 0 Offset 0x4 Length 4
 7 
 8 id = 2                               
 9 
10 Slot 1 Column 1 Offset 0x8 Length 20
11 
12 itemno = 2                           
13 
14 Slot 1 Column 2 Offset 0x1c Length 40
15 
16 itemname = 法國                                                           
17 
18 Slot 2 Offset 0xee Length 71
19 
20 
21 Slot 2 Column 0 Offset 0x4 Length 4
22 
23 id = 3                               
24 
25 Slot 2 Column 1 Offset 0x8 Length 20
26 
27 itemno = 3                           
28 
29 Slot 2 Column 2 Offset 0x1c Length 40
30 
31 itemname = 美國                                                           
32 
33 Slot 3 Offset 0x135 Length 71
34 
35 
36 Slot 3 Column 0 Offset 0x4 Length 4
37 
38 id = 4                               
39 
40 Slot 3 Column 1 Offset 0x8 Length 20
41 
42 itemno = 4                           
43 
44 Slot 3 Column 2 Offset 0x1c Length 40
45 
46 itemname = 英國                                                           
47 
48 Slot 4 Offset 0x17c Length 71
49 
50              
51 
52 Slot 4 Column 0 Offset 0x4 Length 4
53 
54 id = 5                               
55 
56 Slot 4 Column 1 Offset 0x8 Length 20
57 
58 itemno = 5                           
59 
60 Slot 4 Column 2 Offset 0x1c Length 40
61 
62 itemname = 德國  

五條記錄都在同一個數據頁面

參考文章:

http://www.cnblogs.com/zhijianliutang/archive/2012/10/28/2743722.html

 

如有不對的地方,歡迎大家拍磚o(∩_∩)o

----------------------------------------------------------------

2013-10-19 晚上補充

我們用Internal Viewer來查看TEST數據庫

在Internal Viewer查看到TEST數據庫是分區的,十分形象

也能夠看到那3個pageid為8的數據頁面

我們進入第4個文件的數據頁面,即是:E:\FG_TestUnique_Id_02_data.ndf里的數據頁面

可以看到每個數據文件都會有GAM、SGAM、DCM、BCM、PFS頁面

另外的兩個數據頁面我就不打開來看了

關於GAM、SGAM、DCM、BCM、PFS這些頁面的作用可以參考下面文章:

SQL Server 2008 連載之存儲結構之DCM、BCM

SQL Server 2008連載之存儲結構之GAM、SGAM

SQL Server 2008連載之存儲結構之PFS結構


關於索引對齊/分區對齊

大家可以先看一下我之前寫的文章,看一下數據頁面之間是怎麽關聯的,先了解一下

SQLSERVER聚集索引與非聚集索引的再次研究(上)
SQLSERVER聚集索引與非聚集索引的再次研究(下)

MSDN中的解釋

索引分區
除了對表的數據集進行分區之外,還可以對索引進行分區。使用相同的函數對表及其索引進行分區通常可以優化性能。
當索引和表按照相同的順序使用相同的分區函數和列時,表和索引將對齊。如果在已經分區的表中建立索引,
SQL Server 會自動將新索引與該表的分區架構對齊,除非該索引的分區明顯不同。當表及其索引對齊后,
SQL Server 則可以更有效地將分區移入和移出分區表,因為所有相關的數據和索引都使用相同的算法進行划分。
如果定義表和索引時不僅使用了相同的分區函數,還使用了相同的分區架構,則這些表和索引將被認為是按存儲位置對齊。
按存儲位置對齊的一個優點是,相同邊界內的所有數據都位於相同的物理磁盤上。在這種情況下,
可以單獨在某個時間段內執行備份操作,還可以根據數據的變化在備份頻率和備份類型方面改變您的策略。
如果連接或收集了相同文件或文件組中的表和索引,則可以發現更多的好處。SQL Server 可以通過在多個分區中並行操作來獲益。
在按存儲位置對齊和多 CPU 的情況下,每個處理器都可以直接處理特定的文件或文件組,而不會與數據訪問產生任何沖突,
因為所有需要的數據都位於同一個磁盤上。這樣,可以並行運行多個進程,而不會相互干擾。

 

建立索引:是否分區?
默認情況下,分區表中創建的索引也使用相同的分區架構和分區列。
如果屬於這種情況,索引將與表對齊。盡管未作要求,但將表與其索引對齊可以使管理工作更容易進行,
對於滑動窗口方案尤其如此。
例如,要創建唯一的索引,分區列必須是一個關鍵列;這將確保對相應的分區進行驗證,以保證索引的唯一性。
因此,如果需要在一列上對表進行分區,而必須在另一個列上創建唯一的索引,這些表和索引將無法對齊。
在這種情況下,可以在唯一的列(如果是多列的唯一鍵,則可以是任一關鍵列)中對索引進行分區,或者根本就不進行分區。
請注意,在分區表中移入和移出數據時,必須刪除和創建此索引。
注意:如果您打算使用現有數據加載表並立即在其中添加索引,則通常可以通過以下方式獲得更好的性能:
先加載到未分區、未建立索引的表中,然后在加載數據后創建分區索引。
通過為分區架構定義群集索引,可以在加載數據后更有效地為表分區。
這也是為現有表分區的不錯方法。要創建與未分區表相同的表並創建與已分區群集索引相同的群集索引,
請用一個文件組目標位置替換創建表中的 ON 子句。然后,在加載數據之后為分區架構創建群集索引。


索引對齊,簡單來講,因為索引也可以創建在不同的文件組中,那里創建索引的時候也可以根據
分區架構和用來分區的列來創建索引,這樣索引數據和表數據都放在同一個文件組中,叫索引對齊

 ------------------------------------------------------------------------------

聚集索引表

聚集索引建立在分區列

我們drop掉testPartionTable表,重新建立testPartionTable表

 1 --5.創建分區表
 2 CREATE TABLE testPartionTable
 3 (
 4   id INT  NOT NULL,
 5   itemname NVARCHAR(4000)
 6 )ON Sch_TestUnique_Id([id])
 7 
 8 
 9 INSERT INTO [dbo].[testPartionTable] ( [id], [itemname] )
10 SELECT 1,'中國'+REPLICATE('a',3500) UNION ALL
11 SELECT 2,'法國'+REPLICATE('a',3500) UNION ALL
12 SELECT 3,'美國'+REPLICATE('a',3500) UNION ALL
13 SELECT 4,'英國'+REPLICATE('a',3500) UNION ALL
14 SELECT 5,'德國'+REPLICATE('a',3500)
15 
16 SELECT * FROM [dbo].[testPartionTable]
17 GO
18 
19 --查看邊界值點
20 select * from sys.partition_range_values
21 GO
View Code

 

這個表有一個特點:就是一條記錄占用一個數據頁面

創建聚集索引,聚集索引字段創建在分區字段id上

1 --創建聚集索引
2 CREATE CLUSTERED INDEX cix_id ON testPartionTable(id ASC)

我們看一下,創建聚集索引之后,表的頁面的分配情況

1 --TRUNCATE TABLE [dbo].[DBCCResult]
2 INSERT INTO DBCCResult EXEC ('DBCC IND(test,testPartionTable,-1) ')
3 
4 SELECT * FROM [dbo].[DBCCResult] ORDER BY [PageType] DESC
View Code

上圖中,紅色框的列都需要注意的

分區號1/fileid3 (PartitionNumber1)-》文件組FG_TestUnique_Id_01-》E:\FG_TestUnique_Id_01_data.ndf

分區號2/fileid4 (PartitionNumber2)-》文件組FG_TestUnique_Id_02-》E:\FG_TestUnique_Id_02_data.ndf

分區號3/fileid5 (PartitionNumber3)-》文件組FG_TestUnique_Id_03-》E:\FG_TestUnique_Id_03_data.ndf

從上圖可以得出:

fileid3/分區號1:聚集索引頁15,IAM頁13,數據頁12,數據頁14

fileid4/分區號2:聚集索引頁15,IAM頁13,數據頁12,數據頁14

fileid5/分區號3:IAM頁12,數據頁11

 

 fileid          PartitionID
fileid3:72057594038583296
fileid4:72057594038648832
fileid5:72057594038714368

 

PartitionID指的是:表的分區ID,如果一張表沒有使用表分區技術,每張表本來默認會有一個分區

如果使用了表分區技術,那么,每個分區都會有一個分區ID(PartitionID)

 

頁面12既是IAM頁面也是數據頁面

不同的是:一個頁面12在fileid5文件里作為IAM頁面,另一個頁面12在fileid4文件里作為數據頁面

 

可以看到fileid3文件和fileid4文件里的數據頁面是首尾相連的,都標記了與那個文件的哪個頁面進行相連

唯獨fileid5文件里面沒有聚集索引頁面,可能因為只有一個數據頁11,所以沒有聚集索引頁面

而且也看不到fileid5文件里數據頁有首尾相連標記

 

-------------------------------------------------------------------

----------------------------------------------------------------------

頁面指向

文件4里數據頁面12-》文件4里數據頁面14
文件3里數據頁面12-》文件3里數據頁面14

可以看到三個文件組之間或者三個ndf文件之間,數據頁面與數據頁面之間已經沒有聯系了,

只有大家都在同一個ndf文件里才能首尾相連,才有聯系

 

我們看一下聚集索引頁面

fileid為3的聚集索引頁面

1 DBCC TRACEON(3604,-1)
2 GO
3 DBCC PAGE(test,3,15,3)
4 GO

 

fileid為4的聚集索引頁面

1 DBCC TRACEON(3604,-1)
2 GO
3 DBCC PAGE(test,4,15,3)
4 GO

 

每個文件中的聚集索引頁面都各自為政,都只管他自己的文件里的數據頁面,而別的文件里的數據頁面他是不管的

 

我們看一下數據頁面,這里我只顯示有用的信息,數據頁面的其他沒用信息我都刪掉了

1 DBCC TRACEON(3604,-1)
2 GO
3 DBCC PAGE(test,3,12,3)
4 GO
 1 PAGE: (3:12)
 2 
 3 
 4         
 5 UNIQUIFIER = [NULL]                  
 6 
 7 Slot 0 Column 1 Offset 0x4 Length 4
 8 
 9 id = 1                               
10 
11 Slot 0 Column 2 Offset 0x11 Length 7004
12 
13 itemname = 中國aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
14 
15 DBCC 執行完畢。如果 DBCC 輸出了錯誤信息,請與系統管理員聯系。
1 DBCC TRACEON(3604,-1)
2 GO
3 DBCC PAGE(test,3,14,3)
4 GO
 1 PAGE: (3:14)
 2 
 3 
 4       
 5             
 6 UNIQUIFIER = [NULL]                  
 7 
 8 Slot 0 Column 1 Offset 0x4 Length 4
 9 
10 id = 2                               
11 
12 Slot 0 Column 2 Offset 0x11 Length 7004
13 
14 itemname = 法國aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
15 
16 DBCC 執行完畢。如果 DBCC 輸出了錯誤信息,請與系統管理員聯系。

 

1 DBCC TRACEON(3604,-1)
2 GO
3 DBCC PAGE(test,4,12,3)
4 GO
 1 PAGE: (4:12)
 2 
 3 
 4          
 5 UNIQUIFIER = [NULL]                  
 6 
 7 Slot 0 Column 1 Offset 0x4 Length 4
 8 
 9 id = 3                               
10 
11 Slot 0 Column 2 Offset 0x11 Length 7004
12 
13 itemname = 美國aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
14 
15 DBCC 執行完畢。如果 DBCC 輸出了錯誤信息,請與系統管理員聯系。
1 DBCC TRACEON(3604,-1)
2 GO
3 DBCC PAGE(test,4,14,3)
4 GO
 1 PAGE: (4:14)
 2 
 3          
 4 UNIQUIFIER = [NULL]                  
 5 
 6 Slot 0 Column 1 Offset 0x4 Length 4
 7 
 8 id = 4                               
 9 
10 Slot 0 Column 2 Offset 0x11 Length 7004
11 
12 itemname = 英國aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
13 
14 DBCC 執行完畢。如果 DBCC 輸出了錯誤信息,請與系統管理員聯系。

 

1 DBCC TRACEON(3604,-1)
2 GO
3 DBCC PAGE(test,5,11,3)
4 GO
 1 PAGE: (5:11)
 2     
 3 UNIQUIFIER = [NULL]                  
 4 
 5 Slot 0 Column 1 Offset 0x4 Length 4
 6 
 7 id = 5                               
 8 
 9 Slot 0 Column 2 Offset 0x11 Length 7004
10 
11 itemname = 德國aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
12 
13 DBCC 執行完畢。如果 DBCC 輸出了錯誤信息,請與系統管理員聯系。

 

從上面的結果得出:

fileid3:數據頁12存放的 id值為1
fileid3:數據頁14存放的 id值為2

fileid4:數據頁12存放的 id值為3
fileid4:數據頁14存放的 id值為4

fileid5:數據頁11存放的 id值為5

 

fileid3/分區號1:id值為1和2

fileid4/分區號2:id值為3和4

fileid5/分區號3:id值為5

按照了分區函數來分

 1 --我們創建了一個用於數據類型為int的分區函數,按照數值來划分
 2 --文件組                  分區      取值范圍
 3 --[FG_TestUnique_Id_01]    1        (小於2, 2]--包括2
 4 --[FG_TestUnique_Id_02]    2        [3, 4]
 5 --[FG_TestUnique_Id_03]    3        (4,大於4)  --不包括4
 6 
 7 CREATE PARTITION FUNCTION
 8 Fun_TestUnique_Id(INT) AS
 9 RANGE LEFT
10 FOR VALUES(2,4)

而且聚集索引頁面保存的id值也是按照分區函數來分的

fileid3/分區號1:id值為1和2

fileid4/分區號2:id值為3和4

那么這時候可以說聚集索引和數據都按照分區函數來划分,是索引對齊

 

-----------------------------------------------------------------------------------------------------

聚集索引建立在非分區列

我們drop掉testPartionTable表,重新建立testPartionTable表

 1 CREATE TABLE testPartionTable
 2 (
 3   id INT  NOT NULL,
 4   itemno CHAR(20),
 5   itemname NVARCHAR(4000)
 6 )ON Sch_TestUnique_Id([id])
 7 
 8 
 9 
10 
11 
12 INSERT INTO [dbo].[testPartionTable] ( [id],[itemno], [itemname] )
13 SELECT 1,'5','中國'+REPLICATE('a',3500) UNION ALL
14 SELECT 2,'6','法國'+REPLICATE('a',3500) UNION ALL
15 SELECT 3,'3','美國'+REPLICATE('a',3500) UNION ALL
16 SELECT 4,'1','英國'+REPLICATE('a',3500) UNION ALL
17 SELECT 5,'4','德國'+REPLICATE('a',3500) UNION ALL
18 SELECT 6,'2','日本'+REPLICATE('a',3500)
19 
20 SELECT * FROM [dbo].[testPartionTable]
21 GO
22 
23 --查看邊界值點
24 select * from sys.partition_range_values
25 GO
View Code

創建聚集索引之前testPartionTable表頁面分配情況

這次我們將聚集索引創建在非分區字段itemno上

1 --創建聚集索引
2 CREATE CLUSTERED INDEX cix_id ON testPartionTable([itemno] ASC)
3 GO
1 --TRUNCATE TABLE [dbo].[DBCCResult]
2 INSERT INTO DBCCResult EXEC ('DBCC IND(test,testPartionTable,-1) ')
3 
4 SELECT * FROM [dbo].[DBCCResult] ORDER BY [PageType] DESC
View Code

建立聚集索引之后,頁面會重新分配

這個在SQLSERVER聚集索引與非聚集索引的再次研究(下)里已經講過了

從上圖可以得出:

fileid3/分區號1:聚集索引頁23,IAM頁21,數據頁20,數據頁22

fileid4/分區號2:聚集索引頁23,IAM頁21,數據頁20,數據頁22

fileid5/分區號3:聚集索引頁23,IAM頁21,數據頁20,數據頁22

 

這里跟剛才不一樣的是:多了聚集索引頁23

fileid5/分區號3:聚集索引頁23,IAM頁21,數據頁20,數據頁22

fileid5/分區號3(剛才):IAM頁12,數據頁11

 

而且可以看到fileid5文件里數據頁有首尾相連標記

剛才:

現在:

 

這里可以反映出:一個文件/文件組里的數據頁多於一個才會出現聚集索引頁面

 

我們看一下 聚集索引頁面

1 DBCC TRACEON(3604,-1)
2 GO
3 DBCC PAGE(test,3,23,3)
4 GO

1 DBCC TRACEON(3604,-1)
2 GO
3 DBCC PAGE(test,4,23,3)
4 GO

1 DBCC TRACEON(3604,-1)
2 GO
3 DBCC PAGE(test,5,23,3)
4 GO

 

聚集索引頁面告訴我們:雖然我們在itemno字段上建立聚集索引,但是SQLSERVER在聚集索引頁面里

還是以id為聚集索引鍵來建立聚集索引,直白一點來說就是SQLSERVER會在id列上建立聚集索引,按照id字段來進行排序

無論你在非分區列的那個列上建立聚集索引,SQLSERVER都只會在分區列上建立聚集索引(可能有點繞口o(∩_∩)o )

 1 INSERT INTO [dbo].[testPartionTable] ( [id],[itemno], [itemname] )
 2 SELECT 1,'5','中國'+REPLICATE('a',3500) UNION ALL
 3 SELECT 2,'6','法國'+REPLICATE('a',3500) UNION ALL
 4 SELECT 3,'3','美國'+REPLICATE('a',3500) UNION ALL
 5 SELECT 4,'1','英國'+REPLICATE('a',3500) UNION ALL
 6 SELECT 5,'4','德國'+REPLICATE('a',3500) UNION ALL
 7 SELECT 6,'2','日本'+REPLICATE('a',3500)
 8 
 9 --創建聚集索引
10 CREATE CLUSTERED INDEX cix_id ON testPartionTable([itemno] ASC)
11 GO

 

我們看一下數據頁面

 1 PAGE: (3:20)
 2                      
 3 UNIQUIFIER = [NULL]                  
 4 
 5 Slot 0 Column 1 Offset 0x4 Length 20
 6 
 7 itemno = 5                           
 8 
 9 Slot 0 Column 2 Offset 0x18 Length 4
10 
11 id = 1                               
12 
13 Slot 0 Column 3 Offset 0x25 Length 7004
14 
15 itemname = 中國aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
 1 PAGE: (3:22)
 2                      
 3 UNIQUIFIER = [NULL]                  
 4 
 5 Slot 0 Column 1 Offset 0x4 Length 20
 6 
 7 itemno = 6                           
 8 
 9 Slot 0 Column 2 Offset 0x18 Length 4
10 
11 id = 2                               
12 
13 Slot 0 Column 3 Offset 0x25 Length 7004
14 
15 itemname = 法國aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
 1 PAGE: (4:20)
 2                       
 3 UNIQUIFIER = [NULL]                  
 4 
 5 Slot 0 Column 1 Offset 0x4 Length 20
 6 
 7 itemno = 1                           
 8 
 9 Slot 0 Column 2 Offset 0x18 Length 4
10 
11 id = 4                               
12 
13 Slot 0 Column 3 Offset 0x25 Length 7004
14 
15 itemname = 英國aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
 1 PAGE: (4:22)
 2                      
 3 UNIQUIFIER = [NULL]                  
 4 
 5 Slot 0 Column 1 Offset 0x4 Length 20
 6 
 7 itemno = 3                           
 8 
 9 Slot 0 Column 2 Offset 0x18 Length 4
10 
11 id = 3                               
12 
13 Slot 0 Column 3 Offset 0x25 Length 7004
14 
15 itemname = 美國aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
 1 PAGE: (5:20)
 2                        
 3 UNIQUIFIER = [NULL]                  
 4 
 5 Slot 0 Column 1 Offset 0x4 Length 20
 6 
 7 itemno = 2                           
 8 
 9 Slot 0 Column 2 Offset 0x18 Length 4
10 
11 id = 6                               
12 
13 Slot 0 Column 3 Offset 0x25 Length 7004
14 
15 itemname = 日本aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
 1 PAGE: (5:22)
 2                        
 3 UNIQUIFIER = [NULL]                  
 4 
 5 Slot 0 Column 1 Offset 0x4 Length 20
 6 
 7 itemno = 4                           
 8 
 9 Slot 0 Column 2 Offset 0x18 Length 4
10 
11 id = 5                               
12 
13 Slot 0 Column 3 Offset 0x25 Length 7004
14 
15 itemname = 德國aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa

注意:我這里為了節省篇幅,將數據頁面的內容進行了刪減

 

fileid3/分區號1:id值為1和2

fileid4/分區號2:id值為3和4

fileid5/分區號3:id值為5和6

 

那么就是說,對於聚集索引表來說,無論聚集索引建立在分區列還是非分區列,都會索引對齊


非聚集索引表

非聚集索引建立在分區列

我們drop掉數據庫test,重新建立數據庫test

1 USE master
2 GO
3 DROP DATABASE [Test]
4 GO
View Code

SQL腳本都跟剛才一樣的

 1 USE master
 2 GO
 3 
 4 --創建數據庫
 5 CREATE DATABASE [Test]
 6 GO
 7 
 8 USE [Test]
 9 GO
10 
11 
12 --1.創建文件組
13 ALTER DATABASE [Test]
14 ADD FILEGROUP [FG_TestUnique_Id_01]
15 
16 ALTER DATABASE [Test]
17 ADD FILEGROUP [FG_TestUnique_Id_02]
18 
19 ALTER DATABASE [Test]
20 ADD FILEGROUP [FG_TestUnique_Id_03]
21 
22 --2.創建文件
23 ALTER DATABASE [Test]
24 ADD FILE
25 (NAME = N'FG_TestUnique_Id_01_data',FILENAME = N'E:\FG_TestUnique_Id_01_data.ndf',SIZE = 1MB, FILEGROWTH = 1MB )
26 TO FILEGROUP [FG_TestUnique_Id_01];
27 
28 ALTER DATABASE [Test]
29 ADD FILE
30 (NAME = N'FG_TestUnique_Id_02_data',FILENAME = N'E:\FG_TestUnique_Id_02_data.ndf',SIZE = 1MB, FILEGROWTH = 1MB )
31 TO FILEGROUP [FG_TestUnique_Id_02];
32 
33 ALTER DATABASE [Test]
34 ADD FILE
35 (NAME = N'FG_TestUnique_Id_03_data',FILENAME = N'E:\FG_TestUnique_Id_03_data.ndf',SIZE = 1MB, FILEGROWTH = 1MB )
36 TO FILEGROUP [FG_TestUnique_Id_03];
37 
38 
39 --3.創建分區函數
40 --我們創建了一個用於數據類型為int的分區函數,按照數值來划分
41 --文件組                  分區      取值范圍
42 --[FG_TestUnique_Id_01]    1        (小於2, 2]--包括2
43 --[FG_TestUnique_Id_02]    2        [3, 4]
44 --[FG_TestUnique_Id_03]    3        (4,大於4)  --不包括4
45 
46 CREATE PARTITION FUNCTION
47 Fun_TestUnique_Id(INT) AS
48 RANGE LEFT
49 FOR VALUES(2,4)
50 
51 
52 
53 
54 --4.創建分區方案
55 CREATE PARTITION SCHEME
56 Sch_TestUnique_Id AS
57 PARTITION Fun_TestUnique_Id
58 TO([FG_TestUnique_Id_01],[FG_TestUnique_Id_02],[FG_TestUnique_Id_03])
59 
60 --5.創建分區表
61 --DROP TABLE testPartionTable
62 CREATE TABLE testPartionTable
63 (
64   id INT  NOT NULL,
65   itemno CHAR(20),
66   itemname NVARCHAR(4000)
67 )ON Sch_TestUnique_Id([id])
68 
69 
70 
71 
72 
73 INSERT INTO [dbo].[testPartionTable] ( [id],[itemno], [itemname] )
74 SELECT 1,'5','中國'+REPLICATE('a',3500) UNION ALL
75 SELECT 2,'6','法國'+REPLICATE('a',3500) UNION ALL
76 SELECT 3,'3','美國'+REPLICATE('a',3500) UNION ALL
77 SELECT 4,'1','英國'+REPLICATE('a',3500) UNION ALL
78 SELECT 5,'4','德國'+REPLICATE('a',3500) UNION ALL
79 SELECT 6,'2','日本'+REPLICATE('a',3500)
80 
81 SELECT * FROM [dbo].[testPartionTable]
82 GO
83 
84 --查看邊界值點
85 select * from sys.partition_range_values
86 GO
View Code
 1 CREATE TABLE DBCCResult (
 2 PageFID NVARCHAR(200),
 3 PagePID NVARCHAR(200),
 4 IAMFID NVARCHAR(200),
 5 IAMPID NVARCHAR(200),
 6 ObjectID NVARCHAR(200),
 7 IndexID NVARCHAR(200),
 8 PartitionNumber NVARCHAR(200),
 9 PartitionID NVARCHAR(200),
10 iam_chain_type NVARCHAR(200),
11 PageType NVARCHAR(200),
12 IndexLevel NVARCHAR(200),
13 NextPageFID NVARCHAR(200),
14 NextPagePID NVARCHAR(200),
15 PrevPageFID NVARCHAR(200),
16 PrevPagePID NVARCHAR(200)
17 )
18 
19 --TRUNCATE TABLE [dbo].[DBCCResult]
20 INSERT INTO DBCCResult EXEC ('DBCC IND(test,testPartionTable,-1) ')
21 
22 SELECT * FROM [dbo].[DBCCResult] ORDER BY [PageType] DESC
View Code

在id字段上建立非聚集索引

1 --創建非聚集索引
2 CREATE  INDEX cix_id ON testPartionTable([id] ASC)
3 GO
1 --TRUNCATE TABLE [dbo].[DBCCResult]
2 INSERT INTO DBCCResult EXEC ('DBCC IND(test,testPartionTable,-1) ')
3 
4 SELECT * FROM [dbo].[DBCCResult] ORDER BY [PageType] DESC
View Code

 

我們比較一下創建非聚集索引之前和之后的圖片

-----------------------------------------------------------------------------------------------------------------------

放大左下角的圖片

可以看到只是在每個文件fileid3、fileid4、fileid5里新建了非聚集索引頁面12和IAM頁面13,其他什么都沒有改變

 

fileid3/分區號1:非聚集索引頁12,IAM頁13,IAM頁9,數據頁8,數據頁10

fileid4/分區號2:非聚集索引頁12,IAM頁13,IAM頁9,數據頁8,數據頁10

fileid5/分區號3:非聚集索引頁12,IAM頁13,IAM頁9,數據頁8,數據頁10

 

 ----------------------------------------------------------------------------

我們看一下非聚集索引頁面

1 DBCC TRACEON(3604,-1)
2 GO
3 DBCC PAGE(test,3,12,3)
4 GO
View Code

1 DBCC TRACEON(3604,-1)
2 GO
3 DBCC PAGE(test,4,12,3)
4 GO
View Code

1 DBCC TRACEON(3604,-1)
2 GO
3 DBCC PAGE(test,5,12,3)
4 GO
View Code

每個文件中的非聚集索引頁面都各自為政,都只管他自己的文件里的數據頁面,而別的文件里的數據頁面他是不管的

這里HEAP RID(key)只會指向本文件里的數據頁面,不會指向其他文件的數據頁面,因為如果指向其他文件的數據頁面的話

那么就不用每個文件都有一個非聚集索引頁面12了

 

我們看一下數據頁面,這里我只顯示有用的信息,數據頁面的其他沒用信息我都刪掉了

1 DBCC TRACEON(3604,-1)
2 GO
3 DBCC PAGE(test,3,8,3)
4 GO
View Code
 1 PAGE: (3:8)       
 2 
 3 Slot 0 Column 0 Offset 0x4 Length 4
 4 
 5 id = 1                               
 6 
 7 Slot 0 Column 1 Offset 0x8 Length 20
 8 
 9 itemno = 5                           
10 
11 Slot 0 Column 2 Offset 0x23 Length 7004
12 
13 itemname = 中國aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
1 DBCC TRACEON(3604,-1)
2 GO
3 DBCC PAGE(test,3,10,3)
4 GO
View Code
 1 PAGE: (3:10)         
 2 
 3 Slot 0 Column 0 Offset 0x4 Length 4
 4 
 5 id = 2                               
 6 
 7 Slot 0 Column 1 Offset 0x8 Length 20
 8 
 9 itemno = 6                           
10 
11 Slot 0 Column 2 Offset 0x23 Length 7004
12 
13 itemname = 法國aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
1 DBCC TRACEON(3604,-1)
2 GO
3 DBCC PAGE(test,4,8,3)
4 GO
View Code
 1 PAGE: (4:8)         
 2 
 3 Slot 0 Column 0 Offset 0x4 Length 4
 4 
 5 id = 3                               
 6 
 7 Slot 0 Column 1 Offset 0x8 Length 20
 8 
 9 itemno = 3                           
10 
11 Slot 0 Column 2 Offset 0x23 Length 7004
12 
13 itemname = 美國aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
1 DBCC TRACEON(3604,-1)
2 GO
3 DBCC PAGE(test,4,10,3)
4 GO
View Code
 1 PAGE: (4:10)      
 2 
 3 Slot 0 Column 0 Offset 0x4 Length 4
 4 
 5 id = 4                               
 6 
 7 Slot 0 Column 1 Offset 0x8 Length 20
 8 
 9 itemno = 1                           
10 
11 Slot 0 Column 2 Offset 0x23 Length 7004
12 
13 itemname = 英國aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
1 DBCC TRACEON(3604,-1)
2 GO
3 DBCC PAGE(test,5,8,3)
4 GO
View Code
 1 PAGE: (5:8)        
 2 
 3 Slot 0 Column 0 Offset 0x4 Length 4
 4 
 5 id = 5                               
 6 
 7 Slot 0 Column 1 Offset 0x8 Length 20
 8 
 9 itemno = 4                           
10 
11 Slot 0 Column 2 Offset 0x23 Length 7004
12 
13 itemname = 德國aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
1 DBCC TRACEON(3604,-1)
2 GO
3 DBCC PAGE(test,5,10,3)
4 GO
View Code
 1 PAGE: (5:10)        
 2 
 3 Slot 0 Column 0 Offset 0x4 Length 4
 4 
 5 id = 6                               
 6 
 7 Slot 0 Column 1 Offset 0x8 Length 20
 8 
 9 itemno = 2                           
10 
11 Slot 0 Column 2 Offset 0x23 Length 7004
12 
13 itemname = 日本aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa

fileid3/分區號1:id值為1和2

fileid4/分區號2:id值為3和4

fileid5/分區號3:id值為5和6

 

非聚集索引和數據都按照分區函數來划分,是索引對齊


非聚集索引建立在非分區列

我們drop掉testPartionTable表,重新建立testPartionTable表

 1 CREATE TABLE testPartionTable
 2 (
 3   id INT  NOT NULL,
 4   itemno CHAR(20),
 5   itemname NVARCHAR(4000)
 6 )ON Sch_TestUnique_Id([id])
 7 
 8 
 9 
10 
11 
12 INSERT INTO [dbo].[testPartionTable] ( [id],[itemno], [itemname] )
13 SELECT 1,'5','中國'+REPLICATE('a',3500) UNION ALL
14 SELECT 2,'6','法國'+REPLICATE('a',3500) UNION ALL
15 SELECT 3,'3','美國'+REPLICATE('a',3500) UNION ALL
16 SELECT 4,'1','英國'+REPLICATE('a',3500) UNION ALL
17 SELECT 5,'4','德國'+REPLICATE('a',3500) UNION ALL
18 SELECT 6,'2','日本'+REPLICATE('a',3500)
19 
20 SELECT * FROM [dbo].[testPartionTable]
21 GO
22 
23 --查看邊界值點
24 select * from sys.partition_range_values
25 GO
View Code

創建非聚集索引之前testPartionTable表頁面分配情況

這次我們將非聚集索引創建在非分區字段itemno上

1 --創建非聚集索引
2 CREATE  INDEX ix_id ON testPartionTable([itemno] ASC)
3 GO
1 --TRUNCATE TABLE [dbo].[DBCCResult]
2 INSERT INTO DBCCResult EXEC ('DBCC IND(test,testPartionTable,-1) ')
3 
4 SELECT * FROM [dbo].[DBCCResult] ORDER BY [PageType] DESC
View Code

這里跟聚集索引不同,原來的數據頁面不會重新分配

從上圖可以得出:

fileid3/分區號1:非聚集索引頁12,IAM頁13,IAM頁9,數據頁8,數據頁10

fileid4/分區號2:非聚集索引頁12,IAM頁13,IAM頁9,數據頁8,數據頁10

fileid5/分區號3:非聚集索引頁12,IAM頁13,IAM頁9,數據頁8,數據頁10

 

我們看一下非聚集索引頁面

1 DBCC TRACEON(3604,-1)
2 GO
3 DBCC PAGE(test,3,12,3)
4 GO
View Code

1 DBCC TRACEON(3604,-1)
2 GO
3 DBCC PAGE(test,4,12,3)
4 GO
View Code

1 DBCC TRACEON(3604,-1)
2 GO
3 DBCC PAGE(test,5,12,3)
4 GO
View Code

 

 

非聚集索引頁面告訴我們:非聚集索引里面會包含分區依據列,但是索引鍵還是不變還是itemno

 

我們看一下數據頁面

 1 PAGE: (3:8)         
 2 
 3 Slot 0 Column 0 Offset 0x4 Length 4
 4 
 5 id = 1                               
 6 
 7 Slot 0 Column 1 Offset 0x8 Length 20
 8 
 9 itemno = 5                           
10 
11 Slot 0 Column 2 Offset 0x23 Length 7004
12 
13 itemname = 中國aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
 1 PAGE: (3:10)        
 2 
 3 Slot 0 Column 0 Offset 0x4 Length 4
 4 
 5 id = 2                               
 6 
 7 Slot 0 Column 1 Offset 0x8 Length 20
 8 
 9 itemno = 6                           
10 
11 Slot 0 Column 2 Offset 0x23 Length 7004
12 
13 itemname = 法國aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
 1 PAGE: (4:8)          
 2 
 3 Slot 0 Column 0 Offset 0x4 Length 4
 4 
 5 id = 3                               
 6 
 7 Slot 0 Column 1 Offset 0x8 Length 20
 8 
 9 itemno = 3                           
10 
11 Slot 0 Column 2 Offset 0x23 Length 7004
12 
13 itemname = 美國aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
 1 PAGE: (4:10)       
 2 
 3 Slot 0 Column 0 Offset 0x4 Length 4
 4 
 5 id = 4                               
 6 
 7 Slot 0 Column 1 Offset 0x8 Length 20
 8 
 9 itemno = 1                           
10 
11 Slot 0 Column 2 Offset 0x23 Length 7004
12 
13 itemname = 英國aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
 1 PAGE: (5:8)          
 2 
 3 Slot 0 Column 0 Offset 0x4 Length 4
 4 
 5 id = 5                               
 6 
 7 Slot 0 Column 1 Offset 0x8 Length 20
 8 
 9 itemno = 4                           
10 
11 Slot 0 Column 2 Offset 0x23 Length 7004
12 
13 itemname = 德國aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
 1 PAGE: (5:10)        
 2 
 3 Slot 0 Column 0 Offset 0x4 Length 4
 4 
 5 id = 6                               
 6 
 7 Slot 0 Column 1 Offset 0x8 Length 20
 8 
 9 itemno = 2                           
10 
11 Slot 0 Column 2 Offset 0x23 Length 7004
12 
13 itemname = 日本aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa

 

fileid3/分區號1:id值為1和2

fileid4/分區號2:id值為3和4

fileid5/分區號3:id值為5和6

對於非聚集索引表來說,無論非聚集索引建立在分區列還是非分區列,都會索引對齊


補兩張圖

表分區下的聚集索引

 

可以看到每個分區都有兩個數據頁和一個聚集索引頁,而主文件組/fileid1里是沒有任何表數據的

 

表分區下的非聚集索引

可以看到每個分區都有兩個數據頁和一個非聚集索引頁,而主文件組/fileid1里是沒有任何表數據的

這里不知道是不是Intelnals Viewer的BUG,就算是非聚集索引都會顯示為聚集索引

 1 USE [GPOSDB]
 2 GO
 3 CREATE TABLE NONCLUSTEREDtalbe(id int,NAME CHAR(20))
 4 INSERT INTO NONCLUSTEREDtalbe
 5 SELECT 1,'nin' UNION ALL
 6 SELECT 2,'nin' UNION ALL
 7 SELECT 3,'nin' UNION ALL
 8 SELECT 4,'nin' 
 9 
10 CREATE NONCLUSTERED INDEX ix_NONCLUSTEREDtalbe ON NONCLUSTEREDtalbe(id ASC)


總結

 

缺點:這里不但數據分布在多個文件里,連聚集索引頁面和非聚集索引頁面都分布在多個文件里

如果是聚集索引/非聚集索引查找也需要到多個文件里去查找

因為在表分區了之后多個文件組之間/多個ndf文件之間,數據頁面與數據頁面之間已經沒有聯系了

必須到每個ndf文件里的聚集索引頁面/非聚集索引頁面去查找,直到找到所需的數據為止

 

所以,在使用表分區的時候一定要做好分區字段的選擇,避免select * from 表 不加where 分區字段=

造成的掃描所有分區

 

無論是索引頁還是數據頁,將一個頁面在每個分區里都保存一份這就是分區,表分區沒有什么神秘的o(∩_∩)o 

看一下插入和查詢的執行計划

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM