SQL Server之索引解析(二)
1、堆表
堆表通過IAM連線一起,查詢時全表掃描。
1、1 非聚集索引
結構
葉子節點資料結構:行資料結構+Rid(8位元組)
- 中間節點資料結構:
(非聚集非唯一索引)行資料結構+Page(4)+2+ Rid(8位元組)
中間2位元組有疑問?
- (非聚集唯一索引)行資料結構+分割符?+ Page(4)
- 堆表非聚集索引結構
1、2 聚集索引表
組織結構
1.2.1 聚集索引
聚集索引表由根節點(Root Node)、中間節點(Branch Nodes)、葉子節點組成。
如果葉子節點不夠多時,根節點(Root Node)、中間節點(Branch Nodes)將不存在。
- 根節點、中間節點行結構
- 系統頭部資訊(2位元組)+Key+&+PageId
- 葉子節點
- 參見行資料結構
- 插入操作對BTree影響
- 刪除操作對索引樹影響
- 更新操作對索引樹影響
注意事項
1. 聚集索引鍵值不能超過900位元組,因為生成keyhashvalue時,如果大於900位元組效能會有很大影響。Keyhashvalue用於查詢頁的資料行
2. 聚集索引鍵值儘量保持短,每頁只有8096位元組可用。減少中間節點的層數。
3. 聚集索引鍵值採用遞增原則,有利於資料頁連續性,減少BTree調整。
1.2.2 非聚集索引
- 非聚集索引在索引表中資料結構
- 根節點(root nodes)、中間節點(page nodes)結構:2位元組系統資訊+非聚集索引鍵值+ChildPage(4位元組)+Key
- 葉子節點leaf nodes資料結構:2位元組系統資訊+非聚集索引鍵值+ Key(keyhasvalue)
-
索引覆蓋
避免聚集索引查詢
最大鍵列數為 16,最大索引鍵大小為 900 位元組
-
過濾索引
索引tree是否包含部分資料。一部分不需要建立索引,減少索引層數。
2、建立索引規則
- 建立聚集索引規則
- 唯一性 :如果非唯一性,索引節點會增加一列唯一表示。
- 靜態的: 如果對聚集索引鍵值進行更新時,中間節點頁會發生變化,葉子節點頁也會發生變化。操作次數增加,頁空間造成浪費。
- 連續性:非連續性會造成頁分拆,頁空間浪費,碎片增多。
- 鍵值大小:鍵值長度越長,中間節點的層數越多,讀取層數越多,效能下降。
-
索引覆蓋
對常用查詢指定列的索引可以適當增加列覆蓋。
- 非聚集索引
- 資料密度原則:資料密度是指列值唯一的記錄佔總記錄數的百分比,這個比率越高,則說明此列越適合建立索引。
- 複合索引鍵列順序:在索引中,索引的順序主要由索引中的每一個鍵列確定,因此,對於複合索引,索引中的列順序是很重要的,應該優先把資料密度大,選擇性列,儲存空間小的列放在索引鍵列的前面。
- 選擇性原則:選擇性是滿足條件的記錄佔總記錄數的百分比,這個比率應該儘可能低,這樣才能保證通過索引掃描後,只需要從基礎表提取很少的資料。
3、相關工具
3.1 組織分析命令
DBCC IND
用於分析表組織和索引組織查詢命令。
- 命令列
DBCC IND ( { 'dbname' | dbid }, { 'objname' | objid }, { nonclustered indid | 1 | 0 | -1 | -2 } [, partition_number] )
- 引數
- Dbname:資料庫名
- Dbid:資料庫Id
- Objname:表名
- Objid:表ID
- nonclustered indid:非聚集索引ID,-2 根節點 -1 中間節點 Branch Nodes 0 葉子節點、1 所有節點
- 下列查詢語句等同於 DBCC IND
Select * from sys.dm_db_database_page_allocations(DB_ID(), object_id('TestData8000'),NULL,NULL,'DETAILED')
sys.dm_db_database_page_allocations(@DatabaseId , @TableId , @IndexId , @PartionID , @Mode)
- @DatabaseId:資料庫Id
- @TableId:表名
- @indexId:
- @PartionId:分割槽Id
堆表
聚集索引表
查詢結果集,欄位說明
列 |
說明 |
PageFID |
索引所在檔案Id |
PagePid |
索引所在頁Id |
IAMFID |
索引所在IAM檔案Id |
IAMPID |
索引所在IAM的頁Id |
objectId |
物件ID,表物件ID |
IndexId |
索引型別 0堆、1聚集索引、2-250非聚集索引 |
PartitionNumber |
索引所在分割槽編號 |
PartitionId |
索引所在的分割槽Id |
Iam_Chain_Type |
該頁存放的資料型別、in-row data 資料頁或索引頁、Row-overflow-data 溢位資料行頁 Blob data 大檔案型別頁 |
PageType |
資料型別見 頁型別 |
IndexLevel |
索引級別 null 根級,0 葉子級,其他索引級 |
NextPageFID |
雙鏈表前級檔案Id |
NextPagePID |
雙鏈表前級頁Id |
PrevPageFID |
雙鏈表後級檔案Id |
PrevPagePID |
雙鏈表後級頁Id |
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
)
- database name:資料庫名
- file Number:頁所在檔案Id
- Page Number:頁id
- Print 0、1、2、3:不同的級別,3為最高階
--DBCC IND('DataPageTestDb','TestData8000',-1) 先查看錶在資料裡頁資料資訊
--DBCC PAGE(DataPageTestDb,1,8,3) 以文字資訊檢視
--DBCC PAGE(DataPageTestDb,1,8,3) with tableresults,以表格資訊檢視
3.2 查詢計劃
檢視索引情況
--dbcc show_statistics ([tablename], [indexname])
--dbcc show_statistics (TestDataUnIndex, PK_TestDataUnIndex)
命令詳細見
https://docs.microsoft.com/zh-cn/previous-versions/sql/sql-server-2008-r2/ms174384(v=sql.105)
-- 開啟IO開銷統計 set STATISTICS io ON
-- 開啟執行時間統計 set STATISTICS TIME ON
-- Select * from Table
或
3.3 跟蹤程式碼生成的SQL語句
Sql Profiler 用於跟蹤程式生成的語句。
參考文章
https://www.cnblogs.com/yx007/p/7268310.html
下圖用於跟蹤Net sqlclient data provider 產生的語句,net體系應用。
以下語句用於跟蹤,線上執行時,SQL操作用時比較長的語句
SELECT TOP 50 total_worker_time/execution_count AS [Avg CPU Time], (SELECT SUBSTRING(text,statement_start_offset/2, (CASE WHEN statement_end_offset = -1 then LEN(CONVERT(nvarchar(max), text)) * 2 ELSE statement_end_offset end -statement_start_offset)/2) FROM sys.dm_exec_sql_text(sql_handle)) AS query_text, * FROM sys.dm_exec_query_stats ORDER BY [Avg CPU Time] DESC
以下語句用於查詢資料庫死鎖
select request_session_id,OBJECT_NAME(resource_associated_entity_id) tableName from sys.dm_tran_locks where resource_type='OBJECT' use master go --檢索死鎖程序 select spid, blocked, loginame, last_batch, status, cmd, hostname, program_name from sysprocesses where spid in ( select blocked from sysprocesses where blocked <> 0 ) or (blocked <>0) select request_session_id,OBJECT_NAME(resource_associated_entity_id) tableName from sys.dm_tran_locks where resource_type='OBJECT'
4、其他
4.1 資料庫欄位型別及長度
型別 |
位元組數 |
定長 |
變長 |
blob型別 |
uniqueidentifier |
16 |
1 |
||
date |
3 |
1 |
||
time |
5 |
1 |
||
datetime2 |
8 |
1 |
||
datetimeoffset |
10 |
1 |
||
tinyint |
1 |
1 |
||
smallint |
2 |
1 |
||
int |
4 |
1 |
||
smalldatetime |
4 |
1 |
||
real |
4 |
1 |
||
money |
8 |
1 |
||
datetime |
8 |
1 |
||
float |
8 |
1 |
||
sql_variant |
8016 |
1 |
||
bit |
1 |
1 |
||
decimal(18.2) |
9 |
1 |
||
numeric(18.2) |
9 |
1 |
||
varchar(max) |
1 |
|||
nvarchar(max) |
1 |
|||
varbinary(max) |
1 |
|||
XML |
1 |
|||
Image |
1 |
|||
text |
||||
ntext |
||||
varchar() |
1 |
|||
nvarchar() |
1 |
|||
varbinary() |
1 |
|||
char |
1 |
|||
nchar |
1 |