我遇到过这样一种情况,即我的SQL Server数据库表中的数据库操作变得非常慢,因为添加了更多记录(单个插入到包含100万条记录的表为5秒)。
我估计这可能是由于我的数据库中表的碎片索引,因为我有许多表使用(并且需要使用)主键聚簇索引的唯一标识符类型。
如何评估是否属于这种情况,如果存在任何碎片问题,如何解决碎片问题(可能每次部署一次)?
我想要一个适用于SQL Server 2005及更高版本的解决方案(我专门在Azure数据库中使用SQL Server(12.0.2000.8))。
答案 0 :(得分:5)
检查表格上的碎片百分比
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
OR
ALTER INDEX index_name ON table_name REBUILD
- 重组
ALTER INDEX ALL ON table_name REORGANIZE
OR
ALTER INDEX index_name ON table_name REORGANIZE
OR
DBCC DBREINDEX ('table_Name')
https://docs.microsoft.com/en-us/sql/relational-databases/indexes/reorganize-and-rebuild-indexes
答案 1 :(得分:3)
由于您已经知道怀疑存在碎片的表,因此可以使用以下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
OR - 重建表中的所有索引
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:
UPDATE STATISTICS [Database_Name].[Table_Name]
with FULLSCAN
更新索引的统计信息
UPDATE STATISTICS [Database_Name].[Table_Name] Index_Name
with FULLSCAN
我已将这些内容作为单独的查询给您,以便更好地了解正在执行的操作。希望这有帮助
答案 2 :(得分:1)
这是一个SQL查询解决方案,适用于SQL Server 2005及更高版本,可以让你
1)首先找到需要重建或重组的所有索引以减少碎片,然后
2)将结果的前五列的单个复制粘贴到新的查询窗口(删除列标题行),执行将解决大部分结果的所有语句(重建/重新组织索引)数据库中所有表中的当前碎片问题。
注意:如果遇到权限错误,您可能需要确保定位在主模式中,并且您的用户对数据库具有适当的权限。
我将此查询命名为: GetFragmentationOfIndexesAndFirst5ColumnsExecutedResolveFragmentation.sql
with (FILLFACTOR = 80)
我必须相信我用于理解并最终实现此解决方案的两个地方:
在数据库中查找碎片的初始方法: 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-check-index-fragmentation-in-sql-server/
编辑:我在上面的查询中包含了EXEC sp_updatestats
部分,因为在我的情况下,大多数碎片索引都在uniqueidentifier列上,不应该使用默认FILLFACTOR为0(100%),因为以这种方式使用它将不可避免地再次快速导致碎片,因为由于无序创建uniqueidentifier,所以总是需要将插入放在其他行之间。您当然可以更改粘贴值以删除或更改适合您的表/索引的参数。
我还发现,在重建和重新组织索引之后,您将需要执行{{1}},以便统计信息可以赶上索引更改,而不必在将来的查询中逐步执行此操作。