簡體   English   中英

如何快速檢測和解決數據庫的SQL Server索引碎片?

[英]How can I quickly detect and resolve SQL Server Index fragmentation for a database?

我遇到過這樣一種情況:隨着更多記錄的添加,我對許多SQL Server數據庫表的數據庫操作變得非常緩慢(單個插入到具有100萬條記錄的表的5s)。

我估計這可能是由於我的數據庫中表的碎片索引,因為我有許多表使用(並且需要使用)主鍵聚簇索引的uniqueidentifier類型。

我如何評估是否是這種情況,如果存在任何碎片問題,如何解決碎片問題(可能每次部署一次)?

我想要一個適用於SQL Server 2005及更高版本的解決方案(我在Azure數據庫(12.0.2000.8)中專門使用SQL Server)。

檢查表上的碎片百分比

SELECT a.index_id, 
       NAME, 
       avg_fragmentation_in_percent, 
       fragment_count, 
       avg_fragment_size_in_pages 
FROM   sys.Dm_db_index_physical_stats(Db_id('dbName'), Object_id('tableName'), 
       NULL, 
              NULL, NULL) AS a 
       INNER JOIN sys.indexes b 
               ON a.object_id = b.object_id 
                  AND a.index_id = b.index_id 

要修復碎片,請重建或重新組織表上的索引

ALTER INDEX ALL ON table_name REBUILD 

要么

ALTER INDEX index_name ON table_name REBUILD 

- 重組

ALTER INDEX ALL ON table_name REORGANIZE

要么

ALTER INDEX index_name ON table_name REORGANIZE

要么

DBCC DBREINDEX ('table_Name')

https://docs.microsoft.com/en-us/sql/relational-databases/indexes/reorganize-and-rebuild-indexes

由於您已經知道懷疑存在碎片的表,因此可以使用以下T-SQL語句來識別碎片。

要獲取數據庫的數據庫ID:

select name , database_id 
from sys.databases
where name = 'Database_Name'

在表所屬的數據庫下運行這些查詢。

要獲取表的對象ID:

select * from sys.objects where name = 'Table_name'

要在表中查找碎片百分比:

select TableName=object_name(dm.object_id)
       ,IndexName=i.name
       ,IndexType=dm.index_type_desc
       ,[%Fragmented]=avg_fragmentation_in_percent   ,dm.fragment_count      ,dm.page_count      ,dm.avg_fragment_size_in_pages     
,dm.record_count     ,dm.avg_page_space_used_in_percent  from 
sys.dm_db_index_physical_stats(14,420770742,null,null,'SAMPLED') dm 
--Here 14 is the Database ID 
--And 420770742 is the Object ID of the table
join sys.indexes i on dm.object_id=i.object_id and
dm.index_id=i.index_id   order by avg_fragmentation_in_percent desc

如果索引的碎片超過20%,那么我們可以嘗試重建該索引:

ALTER INDEX Index_Name 
ON [Database_name].[Table_Name] REBUILD

或 - 重建表中的所有索引

ALTER INDEX ALL ON [Database_name].[Table_Name]
REBUILD WITH (FILLFACTOR = 80)

或者 - 使用DBCC DBREINDEX

DBCC DBREINDEX ('[Database_name].[ Table_Name]')

DBCC DBREINDEX ('[Database_name].[ Table _Name]', 
'Index_Name, 85)

如果碎片計數低於20%,您可以取消索引重建或ReOrg ..而只是更新該索引/表的統計信息。

要使用FULLSCAN在表上運行更新統計信息:

UPDATE STATISTICS [Database_Name].[Table_Name] 
with FULLSCAN

更新索引的統計信息

UPDATE STATISTICS [Database_Name].[Table_Name] Index_Name
with FULLSCAN

我已將每個問題作為單獨的查詢給您,以便更好地了解正在執行的操作。 希望這可以幫助

這是一個在SQL Server 2005及更高版本中運行的SQL查詢解決方案,它將為您提供幫助

1)首先找到需要重建或重組的所有索引以減少碎片,然后

2)將結果的前五列的單個復制粘貼到新的查詢窗口(刪除列標題行),執行將解決大多數當前碎片問題的所有語句(重建/重組索引)在數據庫的所有表中。

注意:如果遇到權限錯誤,則可能需要確保定位在主模式中,並且用戶具有對數據庫的適當權限。

我將此查詢命名為: GetFragmentationOfIndexesAndFirst5ColumnsExecutedResolveFragmentation.sql

SELECT  
'alter index' as 'reindex_part1',
'[' + dbindexes.[name] + ']' as 'Index',
'on' as 'reindex_part2',
'[' + dbtables.[name] + ']' as 'Table',
CASE WHEN indexstats.avg_fragmentation_in_percent > 30
 THEN 'rebuild with (FILLFACTOR = 80)' ELSE 'reorganize' END as 'reindex_part3',
indexstats.avg_fragmentation_in_percent,
indexstats.page_count,
indexstats.alloc_unit_type_desc,
dbschemas.[name] as 'Schema'
FROM sys.dm_db_index_physical_stats (DB_ID(), NULL, NULL, NULL, NULL) AS indexstats
INNER JOIN sys.tables dbtables on dbtables.[object_id] = indexstats.[object_id]
INNER JOIN sys.schemas dbschemas on dbtables.[schema_id] = dbschemas.[schema_id]
INNER JOIN sys.indexes AS dbindexes ON dbindexes.[object_id] = indexstats.[object_id]
AND indexstats.index_id = dbindexes.index_id
WHERE indexstats.database_id = DB_ID()
AND indexstats.avg_fragmentation_in_percent > 5
ORDER BY indexstats.avg_fragmentation_in_percent desc

我必須相信我用於理解並最終實現此解決方案的兩個地方:

在數據庫中查找碎片的初始方法: https//myadventuresincoding.wordpress.com/2013/05/27/sql-server-check-index-fragmentation-on-all-indexes-in-a-database/

如何解決數據庫中的碎片問題(並且應該通過重組索引來解決5%-30%碎片的准則,並且應該通過重建索引來解決30%+碎片): http//www.passionforsql.com/how -to-檢查索引碎片式-SQL服務器/

編輯:我在上面的查詢中包含了with (FILLFACTOR = 80)部分,因為在我的情況下,大多數碎片索引都在uniqueidentifier列上,不應該使用默認的FILLFACTOR為0(100%)進行索引,因為以這種方式使用它們將不可避免地再次快速導致碎片,因為由於無序創建uniqueidentifier,因此總是需要將插入放在其他行之間。 您當然可以更改粘貼值以刪除或更改適合您的表/索引的參數。

我還發現,在重建和重組索引之后,您將需要執行EXEC sp_updatestats ,以便統計信息可以趕上索引更改,而不必在將來的查詢中逐步執行此操作。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM