SQL SERVER 存儲原理 數據存儲


select * from sys.indexes
select * from sys.partitions
select * from sys.allocation_units
select * from sys.system_internals_allocation_units

select * from sys.system_internals_partition_columns

 

DBCC IND

DBCC PAGE

 

-------------------------------------------------------------------------------------------------------------------------
select object_name(object_id) as name,partition_id,partition_number as pnum,rows,
 allocation_unit_id as au_id,type_desc as page_type_desc,total_pages as pages
from sys.partitions p join sys.allocation_units a
 on p.partition_id = a.container_id
where object_id = object_id('dbo.employee')


select convert(char(8),object_name(i.object_id)) as table_name,
 i.name as index_name,i.index_id,i.type_desc as index_type,
 partition_id,partition_number as pnum,rows,
 allocation_unit_id as au_id,a.type_desc as page_type_desc,total_pages as pages
from sys.indexes i join sys.partitions p on i.object_id = p.object_id and i.index_id = p.index_id
 join sys.allocation_units a on p.partition_id = a.container_id
where i.object_id = object_id('dbo.employee')


select convert(char(8),object_name(i.object_id)) as table_name,
 indexproperty(i.object_id,i.name,'minlen') as minlen,
 i.name as index_name,i.index_id,i.type_desc as index_type,
 partition_id,partition_number as pnum,first_page,rows,
 a.allocation_unit_id as au_id,a.type_desc as page_type_desc,a.total_pages as pages
from sys.indexes i join sys.partitions p on i.object_id = p.object_id and i.index_id = p.index_id
 join sys.system_internals_allocation_units a on p.partition_id = a.container_id
where i.object_id = object_id('dbo.employee')

CREATE FUNCTION convert_page_nums (@page_num binary(6))
   RETURNS varchar(11)
AS
  BEGIN
 RETURN(convert(varchar(2), (convert(int, substring(@page_num, 6, 1))
          * power(2, 8)) +
             (convert(int, substring(@page_num, 5, 1)))) + ':' +
               convert(varchar(11),
 (convert(int, substring(@page_num, 4, 1)) * power(2, 24)) +
 (convert(int, substring(@page_num, 3, 1)) * power(2, 16)) +
 (convert(int, substring(@page_num, 2, 1)) * power(2, 8)) +
 (convert(int, substring(@page_num, 1, 1)))) )
  END;
GO
SELECT dbo.convert_page_nums(0xB60000000100);

dbcc ind (testdenny,fixed,-1)
go

dbcc traceon(3604)
go
dbcc page (testdenny,1,182,1)
go

select c.name as column_name,column_id,max_inrow_length,
 pc.system_type_id,leaf_offset
from sys.system_internals_partition_columns pc
 join sys.partitions p on p.partition_id = pc.partition_id
 join sys.columns c on column_id = partition_column_id and c.object_id = p.object_id
where p.object_id = object_id('dbo.fixed')

 

 

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

DBCC IND has three parameters. The first parameter is the database name or the database ID. The second parameter is the object name or object ID within the database. The third parameter is a specific index ID or one of the values 0, -1, or −2.

Here's the syntax:

DBCC IND ({'dbname' | dbid }, { 
'objname' | objid }, { indid | 0 | -1 | -2 })
0Displays the page numbers for all IAMs and data pages.
-1Displays the page numbers for all IAMs, data pages, and index pages.
-2Displays the page numbers for all IAMs.
indidDisplays the page numbers for all IAMs and index pages for this index. If the index ID is 1 (meaning the clustered index), the data pages are also displayed.

The columns mean:

  • PageFID - the file ID of the page
  • PagePID - the page number in the file
  • IAMFID - the file ID of the IAM page that maps this page (this will be NULL for IAM pages themselves as they're not self-referential)
  • IAMPID - the page number in the file of the IAM page that maps this page
  • ObjectID - the ID of the object this page is part of
  • IndexID - the ID of the index this page is part of
  • PartitionNumber - the partition number (as defined by the partitioning scheme for the index) of the partition this page is part of
  • PartitionID - the internal ID of the partition this page is part of
  • PageType - the page type. Some common ones are:
    • 1 - data page
    • 2 - index page
    • 3 and 4 - text pages
    • 8 - GAM page
    • 9 - SGAM page
    • 10 - IAM page
    • 11 - PFS page
  • IndexLevel - what level the page is at in the index (if at all). Remember that index levels go from 0 at the leaf to N at the root page (except in clustered indexes in SQL Server 2000 and 7.0 - where there's a 0 at the leaf level (data pages) and a 0 at the next level up (first level of index pages))
  • NextPageFID and NextPagePID - the page ID of the next page in the doubly-linked list of pages at this level of the index
  • PrevPageFID and PrevPagePID - the page ID of the previous page in the doubly-linked list of pages at this level of the index

 

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

 

DBCC PAGE 參數DBCC PAGE
(
['database name'|database id], -- can be the actual name or id of the database
file number, -- the file number where the page is found
page number, -- the page number within the file
print option = [0|1|2|3] -- display option; each option provides differing levels of information
)

  首先,讓我們來創建一個示例數據庫和表,這將有利於我們描述通過DBCC PAGE你看到了什麼。

  USEMASTER
  GO
  CREATEDATABASEMSSQLTIPS
  GO
  USEMSSQLTIPS
  GO
  CREATETABLEDBO.EMPLOYEE
  (
  EMPLOYEEIDINTIDENTITY(1,1),
  FIRSTNAMEVARCHAR(50)NOTNULL,
  LASTNAMEVARCHAR(50)NOTNULL,
  DATE_HIREDDATETIMENOTNULL,
  IS_ACTIVEBITNOTNULLDEFAULT1,
  CONSTRAINTPK_EMPLOYEEPRIMARYKEY(EMPLOYEEID),
  CONSTRAINTUQ_EMPLOYEE_LASTNAMEUNIQUE(LASTNAME,FIRSTNAME)
  )
  GO
  INSERTINTODBO.EMPLOYEE(FIRSTNAME,LASTNAME,DATE_HIRED)
  SELECT'George','Washington','1999-03-15'
  GO
  INSERTINTODBO.EMPLOYEE(FIRSTNAME,LASTNAME,DATE_HIRED)
  SELECT'Benjamin','Franklin','2001-07-05'
  GO
  INSERTINTODBO.EMPLOYEE(FIRSTNAME,LASTNAME,DATE_HIRED)
  SELECT'Thomas','Jefferson','2002-11-10'
  GO

利用DBCC PAGE查看SQL Server中的表和索引數據。

  現在,我們可以去看看SQL Server如何存儲數據和索引頁。但是我們該從哪裏開始?我們能從哪裏找到這張表的頁和它的數據的所在?其實,這裏還有另外的DBCC命令 – DBCC IND – 你可以用它來列出一張表的所有數據和索引頁。

DBCC IND參數DBCC IND
(
['database name'|database id], -- the database to use
table name, -- the table name to list results
index id, -- an index_id from sys.indexes; -1 shows all indexes and IAMs, -2 just show IAMs
)

  讓我們通過運行下面的命令行來列出EMPLOYEE表的頁結構。

  ListdataandindexpagesallocatedtotheEMPLOYEEtable
  DBCCIND('MSSQLTIPS',EMPLOYEE,-1)
  GO

  以下是我的數據庫所輸出的結果:

利用DBCC PAGE查看SQL Server中的表和索引數據

  請注意,爲了更簡潔,上述的圖像只列出了執行DBCC命令後輸出的前面11列的結果。還有另外的列沒有列出來,這些列包括可以讓你看到這些頁如何彼此關聯的鏈接列表信息。

  這一次的數據意味着什麼呢?爲了達到這篇文章講述的方法的目的,我們專注於一些關鍵列。列PageFID和PagePID分別代表頁所在的文件數目和數據在文件內的頁數目。IndexID是在sys.indexes之中找到的索引的index_id。PageType表示頁的類型,Type = 1是數據頁,Type = 2是索引頁,Type = 10是保存頁本身的IAM頁。IndexLevel是按頁數時IAM結構的級別。如果 level = 0,那麼這是索引的葉級別頁。要想了解更多這些列的詳細信息(畢竟這是一個沒有在正式文件中說明的命令),可以看看由微軟前存儲引擎專家Paul Randal寫的MSDN blog,這個博客很詳細地解釋了這些。

 有了這些信息,現在我們可以看看我們插入的Washington, Franklin和Jefferson三行是如何存儲到EMPLOYEE表中的。EMPLOYEE表有一個聚簇索引(主鍵定義的結果),它表示應該有一個由DBCC IND輸出結果產生的IndexID = 1(index_id = 1指向聚簇索引,在這個聚簇索引中,對於表來說葉級別頁是真正的數據)。觀察由DBCC IND產生的輸出結果,我們可以看到,這個PageType = 1聚簇索引可以在文件數(PageFID) = 1和頁碼(PagePID) = 143的地方找到。這裏有四個不同的顯示頁數據的打印選項。我使用的是包含頁標題信息和數據的打印選項3。

  注意:在我們能夠運行DBCC PAGE之前,要求跟蹤標誌3604設置成指導引擎去發送輸出結果到控制檯,否則你將什麼都看不到。

  DBCCTRACEON(3604)
  DBCCPAGE('MSSQLTIPS',1,143,3)WITHTABLERESULTS
  GO

  滾動到這些結果的結尾處,我們可以看到,我們的數據已經存儲了並且它存儲在聚簇索引的列上。數據行存儲在以零點偏移開始的槽變量上。

利用DBCC PAGE查看SQL Server中的表和索引數據

  EMPLOYEE表也有一個非聚簇索引(通過在表中定義的約束)。讓我們查看創建的非聚簇索引。再次觀察DBCC IND輸出,我們可以很容易確定非聚簇頁,因爲它是IndexID = 2 (PageType = 2)並且它可以在文件數(PageFID)= 1和頁碼(PagePID) = 153中找到。注意,如果我們有表上的不同索引,我們可以查看sys.indexes並且得到隨後要用來查看具體索引的index_id。現在,讓我們來看看索引數據:

  DBCCPAGE('MSSQLTIPS',1,153,3)WITHTABLERESULTS
  GO

 滾動到這些結果的末端,我們可以看到我們的索引數據是按姓和名的邏輯排列來存儲的。你也應該注意到,聚簇索引鍵也存儲在索引行中。當需要一個書籤查找(bookmark lookup)時,引擎可以用它來檢索聚簇索引(這種類型的查找發生在索引欄沒有包含需要用來滿足一個查詢的所有欄時)。

利用DBCC PAGE查看SQL Server中的表和索引數據

  如果這裏沒有表上的聚簇索引,那麼另外的欄將會指向實際的數據頁。讓我們重新創建作爲非聚簇索引的主鍵並且重新檢查由UNIQUE約束創建的非聚簇索引。注意,通過重新創建沒有聚簇索引的表,基本頁的數據已經改變了。通過DBCC IND,你可以看到這些頁結構如何改變。

  ALTERTABLEDBO.EMPLOYEEDROPCONSTRAINTPK_EMPLOYEE
  GO
  ALTERTABLEDBO.EMPLOYEEADDCONSTRAINTPK_EMPLOYEE
  PRIMARYKEYNONCLUSTERED(EMPLOYEEID)
  GO
  DBCCIND('MSSQLTIPS',EMPLOYEE,-1)
  DBCCPAGE('MSSQLTIPS',1,155,3)WITHTABLERESULTS
  GO

利用DBCC PAGE查看SQL Server中的表和索引數據

利用DBCC PAGE查看SQL Server中的表和索引數據

  正如你所看到的,在HEAP表中的索引(這張表不是聚簇的)存儲了一個不同的指示器,這個指示器直接指向包含要求的另外的數據的頁面。

 

  這些都是很簡單的例子,但是它們對給你關於如何和在哪裏獲得和顯示數表和索引數據的想法是綽綽有餘的。在以後的方法中,我將利用更多的例子來說明問題,這些例子將顯示當一行改變並且它不適合某一頁時將會發生什麼,當行被刪除時將發生什麼,還有DBCC PAGE如何幫助解決阻塞和死鎖問題。

  我必須強調,DBCC IND和DBCC PAGE沒有在正式文件中說明,它們可能在以後的SQL Server版本中會消失。在那出現之前,我會繼續利用這些命令作爲窺探引擎的數據存儲技術和解決SQL Server問題的主要工具。

發佈了25 篇原創文章 · 獲贊 6 · 訪問量 13萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章