1. 程式人生 > >利用sys.dm_db_index_physical_stats查看索引大小/碎片等信息

利用sys.dm_db_index_physical_stats查看索引大小/碎片等信息

動態 rom 級別 tex 所在 新建 包含 blank detailed

我們都知道,提高sql server的數據查詢速度,最有效的方法,就是為表創建索引,而我們對數據表進行新增,刪除,修改的時候,會產生索引碎片,索引碎片多了,對性能產生很大的影響,索引碎片越多對數據庫查詢的性能影響就越大,這時我們就需要對索引重新組織或重新生成,以達到索引的最大效率。

www.2cto.com
在sqlserver中索引碎片的大小是以百分比來體現的,如果索引碎片的百分比大於30%以上,就會對影響查詢的性能。這時候我們就需要對該索引進行重新組織或重新生成了,重新組織或重新生成之後,索引碎片就會被刪除。 那我們怎麽才能知道每張表索引碎片的大小呢?方法有兩種:
第一種:
技術分享
1.右鍵索引,選擇“全部重新組織”,會顯示當前表全部所有索引,這是就可以看到“碎片總計”值是以百分比體現的,這時如果值有超過30%的,就要考慮是否要重新組織了。
www.2cto.com
技術分享

2.如果要重新組織的話,點擊“確定”即可。 第二種:利用 sys.dm_db_index_physical_stats 動態函數來查看索引的碎片比率 sys.dm_db_index_physical_stats的定義: sys.dm_db_index_physical_stats (
{database_id | NULL }
, { object_id | NULL }
, { index_id | NULL | 0 }
, { partition_number | NULL }
, { mode | NULL | DEFAULT }
)
參數解釋: database_id--要查看索引所在數據庫,當前數據庫ID我們可以用db_id()函數來取到
object_id--要查索引所在表的id,比如我們要查看表T1,可以用object_id(‘T1‘)來取到該表的ID
index_id--要查看索引的索引號,該索引也同樣可以用object_id(‘索引名‘)來獲取
www.2cto.com
partition_number--對象中的分區號。partition_number為int類型。有效的輸入包括索引或堆的 partion_number 或 NULL
mode--
函數的執行模式將確定為了獲取此函數所使用的統計信息數據而執行的掃描級別。mode 被指定為 LIMITED、SAMPLED 或 DETAILED。此函數將遍歷構成表或索引的指定分區的分配單元頁鏈。
LIMITED:模式運行最快,掃描的頁數最少。對於堆,它將掃描所有頁,但對於索引,則只掃描葉級上面的父級別頁。 SAMPLED:模式將返回基於索引或堆中所有頁的 1% 樣本的統計信息。如果索引或堆少於 10,000 頁,則使用DETAILED模式代替 SAMPLED。 DETAILED:模式將掃描所有頁並返回所有統計信息。 從 LIMITED 到 DETAILED 模式,速度將越來越慢,因為在每個模式中執行的任務越來越多。若要快速測量表或索引的大小或碎片級別,請使用 LIMITED 模式。它的速度最快,並且對於索引的IN_ROW_DATA 分配單元中的每個非葉級別,不返回與其對應的一行。
www.2cto.com 下面通過示例來查看:
比如我要查看當前數據庫的dbo.Orders表的索引情況,可以用以下的語句查詢: SELECT * FROM sys.dm_db_index_physical_stats(db_id(),object_id(‘dbo.Orders‘),null,null,null) 有用的列名解釋: database_id:當前數據庫ID,也就是db_id()
object_id列:當前表的ID,也就是object_id(‘dbo.Orders‘)
index_id列:當前索引的ID,假如dbo.Orders中有兩個索引,index_id分別為1和2,如果我們只想查看索引1的情況,可以用
select * from sys.dm_db_index_physical_stats(db_id(),object_id(‘dbo.Orders‘),1,null,null)
partition_number列:當前索引所在分區號,同sys.dm_db_index_physical_stats定義中的partition_number參數
index_type_desc列:索引類型-聚集索引或者非聚集索引等。
alloc_unit_type_desc列:分配單元類型--這個在下面解釋
avg_fragmentation_in_percent列:最重要的列,當前索引碎片比率。 分配單元類型講解:
IN_ROW_DATA:包含除大型對象 (LOB) 數據以外的所有數據的數據行或索引行。頁的類型為 Data 或 Index。

LOB_DATA:以下列一種或多種數據類型存儲的大型對象數據:text、ntext、image、xml、varchar(max)、nvarchar(max)、varbinary(max) 或 CLR 用戶定義類型 (CLR UDT)。頁的類型為 Text/Image。

ROW_OVERFLOW_DATA:存儲在超過 8,060 字節行大小限制的 varchar、nvarchar、varbinary 或 sql_variant 列中的可變長度數據。頁的類型為 Data。 註意:有時候,我們只為表創建了一個索引,但通過sys.dm_db_index_physical_stats卻查出了兩條記錄,這就是因為在表中使用了text、ntext、image、varchar(max)、nvarchar(max)、varbinary(max)和xml列,也就是LOB_DATA存儲單元.使用了這些列後,在創建表但未插入數據前只有一條記錄,但有插入過數據後,就會有兩條記錄了,兩條記的區別就是alloc_unit_type_desc中的值的區別,可能的情況就是一條的值是N_ROW_DATA,另一條的值是LOB_DATA。
www.2cto.com
我們可以通過一個例子來測試:
首先,新建一個表並且建立一個聚合索引: CREATE TABLE TestTable(rows NCHAR (200) ,rows2 NVARCHAR (max) )
CREATE CLUSTERED INDEX _data_index_TestTable ON TestTable(rows) 在沒有插入數據的情況下: SELECT * FROM TestTable
SELECT * FROM sys.dm_db_index_physical_stats(DB_ID(),OBJECT_ID(‘TestTable‘),null,null,null) 如下圖,在創建表但未插入數據前只有一條記錄: 技術分享

然後,插入數據的情況下:
www.2cto.com INSERT INTO TestTable SELECT REPLICATE(‘li‘,50),REPLICATE(‘hongkong_8‘,2000)
SELECT * FROM TestTable
SELECT * FROM sys.dm_db_index_physical_stats(DB_ID(),OBJECT_ID (‘TestTable‘),null,null,null)如下圖, 如下圖,出現了兩條記錄,這就是因為在表中使用了nvarchar(max)列,也就是LOB_DATA存儲單元 技術分享

利用sys.dm_db_index_physical_stats查看索引大小/碎片等信息