一、索引使用情况
1.查找缺失索引
use DB_name
SELECT A.USER_SEEKS 查找次数,A.USER_SCANS 扫描次数,
ROUND(A.AVG_TOTAL_USER_COST,2) 减少的用户查询的平均成本,A.AVG_USER_IMPACT 可能获得的平均百分比收益,
ROUND((A.USER_SEEKS+A.USER_SCANS)*A.AVG_TOTAL_USER_COST*A.AVG_USER_IMPACT/100,2) 可能的改进优势,
A.LAST_USER_SEEK 最近查找时间,A.LAST_USER_SCAN 最近扫描时间,C.[STATEMENT] 表名,
'CREATE INDEX [IDX_'
+CONVERT(VARCHAR,A.GROUP_HANDLE)+'_'+CONVERT(VARCHAR,C.INDEX_HANDLE)+'_'+REPLACE(REPLACE(REPLACE(C.[STATEMENT],']',''),'[',''),'.','')
+']'+' ON '+C.[STATEMENT]+ ' ('
+ISNULL(C.EQUALITY_COLUMNS,'')
+CASE WHEN NOT C.EQUALITY_COLUMNS IS NULL AND NOT C.INEQUALITY_COLUMNS IS NULL THEN ',' ELSE '' END
+ISNULL(C.INEQUALITY_COLUMNS,'')
+')'
+ISNULL(' INCLUDE ('+C.INCLUDED_COLUMNS+')','') '创建语句'
FROM sys.dm_db_missing_index_group_stats A INNER JOIN sys.dm_db_missing_index_groups B ON A.GROUP_HANDLE=B.INDEX_GROUP_HANDLE
INNER JOIN sys.dm_db_missing_index_details C ON B.INDEX_HANDLE=C.INDEX_HANDLE
WHERE C.DATABASE_ID=DB_ID() --默认当前数据库,若指定数据库则使用DB_ID(['DB_NAME'])
ORDER BY ROUND(A.USER_SEEKS*A.AVG_TOTAL_USER_COST*A.AVG_USER_IMPACT/100,2) DESC
2.查找未使用索引
use DB_name
SELECT C.NAME 表名,B.INDEX_ID 索引ID,B.NAME 索引名,
A.USER_SEEKS 搜索次数,A.USER_SCANS 扫描次数,A.USER_LOOKUPS 查找次数,
A.USER_UPDATES 更新次数,E.TABLEROWS 表行数,
'DROP INDEX '+QUOTENAME(B.NAME)+' ON '+QUOTENAME(D.NAME)+'.'+QUOTENAME(OBJECT_NAME(A.OBJECT_ID)) '删除语句'
FROM sys.dm_db_index_usage_stats A INNER JOIN sys.indexes B ON A.INDEX_ID=B.INDEX_ID AND A.OBJECT_ID=B.OBJECT_ID
INNER JOIN sys.objects C ON A.OBJECT_ID=C.OBJECT_ID
INNER JOIN sys.schemas D ON C.schema_id=D.schema_id
INNER JOIN
(
SELECT INDEX_ID,OBJECT_ID,SUM(ROWS) TABLEROWS
FROM sys.partitions
GROUP BY INDEX_ID,OBJECT_ID
) E ON A.INDEX_ID=E.INDEX_ID AND A.OBJECT_ID=E.OBJECT_ID
WHERE OBJECTPROPERTY(A.OBJECT_ID,'IsUserTable')=1 AND A.DATABASE_ID=DB_ID()
AND B.TYPE_DESC='NONCLUSTERED' AND B.IS_PRIMARY_KEY=0 AND B.IS_UNIQUE_CONSTRAINT=0
--AND C.NAME='INVMB' --根据实际修改表名
ORDER BY (A.USER_SEEKS+A.USER_SCANS+A.USER_LOOKUPS) ASC
当更新次数很大而搜索次数及扫描次数很小或为0时,说明该索引一直在更新但基本不被使用,因而也未对查询提供多少帮助,所以可以考虑删除。
3.查看索引使用情况
use DB_name
SELECT OBJECT_NAME(A.[OBJECT_ID]) 表名,B.INDEX_ID 索引ID,B.[NAME] 索引名称,B.[TYPE_DESC] 索引类型,
A.USER_SEEKS+A.USER_SCANS+A.USER_LOOKUPS 读,A.USER_UPDATES 写,B.FILL_FACTOR 填充因子
FROM sys.dm_db_index_usage_stats A INNER JOIN sys.indexes B ON A.[OBJECT_ID]=B.[OBJECT_ID] AND A.INDEX_ID=B.INDEX_ID
WHERE OBJECTPROPERTY(A.[OBJECT_ID],'ISUSERTABLE')=1
AND A.DATABASE_ID=DB_ID() --默认当前数据库,若指定数据库则使用DB_ID(['DB_NAME'])
ORDER BY OBJECT_NAME(A.[OBJECT_ID]),A.USER_UPDATES DESC,A.USER_SEEKS+A.USER_SCANS+A.USER_LOOKUPS DESC
二、索引碎片维护
1.产生原因及影响
索引是数据库引擎中针对表(有时候也针对视图)建立的特别数据结构,用来帮助查找和整理数据,它的重要性体现在能够使数据库引擎快速返回查询结果。当对索引所在的基础数据表进行增删改时,若存储的数据进行了不适当的跨页(SQL Server中存储的最小单位是页,页是不可再分的),就会导致索引碎片的产生。随着索引碎片的不断增多,查询响应时间就会变慢,性能也因此而下降。要解决这个问题,可以通过重新生成或重新组织索引来解决
2.碎片分类
2.1、外部碎片
当索引页不在逻辑顺序上时就会产生外部碎片。索引创建时,索引键按照逻辑顺序放在一组索引页上。当新数据插入索引时,新的键可能放在存在的键之间。为了让新的键按照正确的顺序插入,可能会创建新的索引页来存储需要移动的那些存在的键。这些新的索引页通常物理上不会和那些被移动的键原来所在的页相邻。创建新页的过程会引起索引页偏离逻辑顺序
外部检测也是用LIMITED模式的sys.dm_db_index_physical_stats,但我们使用avg_fragmentation_in_percent 的结果来检测外部碎片。使用LIMITED模式会给我们叶子层的碎片。如果要获得非页层的碎片,可以使用DETAILED或SAMPLE模式。碎片是页的连续分配。例如如果一个索引有150页,页分配从1到50,55到60,65到120,还有140到180。每个这样序列被称为碎片,这里就是有4个碎片。
use DB_NAME
EXEC sp_configure 'show advanced options', 1
GO
RECONFIGURE WITH OVERRIDE
GO
DECLARE @DefaultFillFactor INT
DECLARE @Fillfactor TABLE
(
Name VARCHAR(100) ,
Minimum INT ,
Maximum INT ,
config_value INT ,
run_value INT
)
INSERT INTO @Fillfactor
EXEC sp_configure 'fill factor (%)'
SELECT @DefaultFillFactor = CASE WHEN run_value = 0 THEN 100
ELSE run_value
END
FROM @Fillfactor
SELECT DB_NAME() AS DBname ,
QUOTENAME(s.name) AS CchemaName ,
QUOTENAME(o.name) AS TableName ,
i.name AS IndexName ,
stats.Index_type_desc AS IndexType ,
stats.page_count AS [PageCount] ,
stats.partition_number AS PartitionNumber ,
CASE WHEN i.fill_factor > 0 THEN i.fill_factor
ELSE @DefaultFillFactor
END AS [Fill Factor] ,
stats.avg_fragmentation_in_percent ,
stats.fragment_count ,
CASE WHEN stats.index_level = 0 THEN 'Leaf Level'
ELSE 'Nonleaf Level'
END AS IndexLevel
FROM sys.dm_db_index_physical_stats(DB_ID(), NULL, NULL, NULL, 'LIMITED')
AS stats ,
sys.objects AS o ,
sys.schemas AS s ,
sys.indexes AS i
WHERE o.OBJECT_ID = stats.OBJECT_ID
AND s.schema_id = o.schema_id
AND i.OBJECT_ID = stats.OBJECT_ID
AND i.index_id = stats.index_id
AND stats.avg_fragmentation_in_percent >= 20
AND stats.page_count >= 1000
ORDER BY stats.avg_fragmentation_in_percent DESC ,
stats.page_count DESC
在这个查询里,我使用的WHERE条件只列出碎片大于20%且最少1000页的索引。avg_fragmentation_in_percent 值高的话,可能有下列原因:
- SQL Server存储引擎对表或索引从混合区开始分配页,直到页数达到8页。一旦页数达到8页,SQL Server引擎开始把整个统一区分配给索引。因此这里对于小表会有很高的碎片,重建索引会增加碎片。例如,我们假设一个索引有7页,这些页是从2个混合区分配的,当我们重建索引的时候,很可能把页分配从2个混合区变成最大7个混合区,这就导致了碎片增加。
- 即使也从混合区分配,还是有碎片产生的可能。当索引大小增长时,在非页层也需要更多的页。如果分配给叶子层的最后页是250,在叶子层索引结构里增加更多的记录,可能会在第1层索引需要更多的页,然后SQL Server存储引擎分配251页在第1层索引,这就在叶子层产生了碎片。
- 造成分页的其他常见原因就是DML操作。Rebuild/Reorganize 索引对于上述不能很好的减少碎片,但可以减少由分页或删除操作造成的碎片。
- 我们按下列要求进行索引的维护:
- 20-40%的碎片,用Reorganize来重新组织索引。
- 大于40%的碎片,需要用Rebuild来重建索引。
- 低于1000页的索引,在索引维护逻辑上是被忽略的(不处理)
- 大于50k的页,碎片在10-20%之间,也要用Reorganize来重新组织索引
2.2、内部碎片
当索引页没有用到最大量时就产生了内部碎片。虽然在一个有频繁数据插入的应用程序里这也许有帮助,然而设置一个fill factor(填充因子)会在索引页上留下空间,服务器内部碎片会导致索引尺寸增加,从而在返回需要的数据时要执行额外的读操作。这些额外的读操作会降低查询的性能。
可以用DETAILED模式的 sys.dm_db_index_physical_stats,avg_page_space_used_in_percent 列会给出索引的内部碎片
use DB_NAME
EXEC sp_configure 'show advanced options', 1
GO
RECONFIGURE WITH OVERRIDE
GO
DECLARE @DefaultFillFactor INT
DECLARE @Fillfactor TABLE
(
Name VARCHAR(100) ,
Minimum INT ,
Maximum INT ,
config_value INT ,
run_value INT
)
INSERT INTO @Fillfactor
EXEC sp_configure 'fill factor (%)'
SELECT @DefaultFillFactor = CASE WHEN run_value = 0 THEN 100
ELSE run_value
END
FROM @Fillfactor
SELECT DB_NAME() AS DBname ,
QUOTENAME(s.name) AS CchemaName ,
QUOTENAME(o.name) AS TableName ,
i.name AS IndexName ,
stats.Index_type_desc AS IndexType ,
stats.page_count AS [PageCount] ,
stats.partition_number AS PartitionNumber ,
CASE WHEN i.fill_factor > 0 THEN i.fill_factor
ELSE @DefaultFillFactor
END AS [Fill Factor] ,
stats.avg_page_space_used_in_percent ,
CASE WHEN stats.index_level = 0 THEN 'Leaf Level'
ELSE 'Nonleaf Level'
END AS IndexLevel
FROM sys.dm_db_index_physical_stats(DB_ID(), NULL, NULL, NULL, 'DETAILED')
AS stats ,
sys.objects AS o ,
sys.schemas AS s ,
sys.indexes AS i
WHERE o.OBJECT_ID = stats.OBJECT_ID
AND s.schema_id = o.schema_id
AND i.OBJECT_ID = stats.OBJECT_ID
AND i.index_id = stats.index_id
AND stats.avg_page_space_used_in_percent <= 85
AND stats.page_count >= 10
AND stats.index_id > 0
ORDER BY stats.avg_page_space_used_in_percent ASC ,
stats.page_count DESC
- 查看单个表
use DB_NAME
-- 创建变量 指定要查看的表
declare @table_id int
set @table_id=object_id('Table_name') -- 修改成自己的表名字
-- 执行
dbcc showcontig(@table_id)
-- 执行结果
DBCC SHOWCONTIG 正在扫描 'Order' 表...
表: 'Order' (1042818777);索引 ID: 0,数据库 ID: 29
已执行 TABLE 级别的扫描。
- 扫描页数................................: 129096
- 扫描区数..............................: 16140
- 区切换次数..............................: 16139
- 每个区的平均页数........................: 8.0
- 扫描密度 [最佳计数:实际计数].......: 99.98% [16137:16140]
- 区扫描碎片 ..................: 24.26%
- 每页的平均可用字节数.....................: 685.2
- 平均页密度(满).....................: 91.53%
DBCC 执行完毕。如果 DBCC 输出了错误信息,请与系统管理员联系。
-- 针对所有级别
USE biyin
DBCC SHOWCONTIG('FundAccountMoneyFlow') WITH ALL_INDEXES
-- 执行结果
DBCC SHOWCONTIG 正在扫描 'FundAccountMoneyFlow' 表...
表: 'FundAccountMoneyFlow' (1957582012);索引 ID: 0,数据库 ID: 29
已执行 TABLE 级别的扫描。
- 扫描页数................................: 26485
- 扫描区数..............................: 3312
- 区切换次数..............................: 3311
- 每个区的平均页数........................: 8.0
- 扫描密度 [最佳计数:实际计数].......: 99.97% [3311:3312]
- 区扫描碎片 ..................: 63.53%
- 每页的平均可用字节数.....................: 375.9
- 平均页密度(满).....................: 95.36%
DBCC SHOWCONTIG 正在扫描 'FundAccountMoneyFlow' 表...
表: 'FundAccountMoneyFlow' (1957582012);索引 ID: 2,数据库 ID: 29
已执行 LEAF 级别的扫描。
- 扫描页数................................: 1465
- 扫描区数..............................: 185
- 区切换次数..............................: 204
- 每个区的平均页数........................: 7.9
- 扫描密度 [最佳计数:实际计数].......: 89.76% [184:205]
- 逻辑扫描碎片 ..................: 5.05%
- 区扫描碎片 ..................: 98.92%
- 每页的平均可用字节数.....................: 7.2
- 平均页密度(满).....................: 99.91%
DBCC SHOWCONTIG 正在扫描 'FundAccountMoneyFlow' 表...
表: 'FundAccountMoneyFlow' (1957582012);索引 ID: 15,数据库 ID: 29
已执行 LEAF 级别的扫描。
- 扫描页数................................: 2919
- 扫描区数..............................: 368
- 区切换次数..............................: 2875
- 每个区的平均页数........................: 7.9
- 扫描密度 [最佳计数:实际计数].......: 12.69% [365:2876]
- 逻辑扫描碎片 ..................: 99.04%
- 区扫描碎片 ..................: 95.38%
- 每页的平均可用字节数.....................: 3298.2
- 平均页密度(满).....................: 59.25%
DBCC SHOWCONTIG 正在扫描 'FundAccountMoneyFlow' 表...
表: 'FundAccountMoneyFlow' (1957582012);索引 ID: 16,数据库 ID: 29
已执行 LEAF 级别的扫描。
- 扫描页数................................: 3142
- 扫描区数..............................: 397
- 区切换次数..............................: 2435
- 每个区的平均页数........................: 7.9
- 扫描密度 [最佳计数:实际计数].......: 16.13% [393:2436]
- 逻辑扫描碎片 ..................: 75.97%
- 区扫描碎片 ..................: 93.95%
- 每页的平均可用字节数.....................: 2267.3
- 平均页密度(满).....................: 71.99%
DBCC 执行完毕。如果 DBCC 输出了错误信息,请与系统管理员联系。
完成时间: 2023-04-20T15:36:10.6177732+08:00
基本指标
扫描密度(%)[最佳计数:实际计数]:这是“最佳计数”与“实际计数”的比率。如果所有内容都是连续的,则该值为 100;如果该值小于 100,则存在一些碎片。“最佳计数”是指在一切都连续链接的情况下,区更改的理想数目。“实际计数”是指区更改的实际次数。
逻辑扫描碎片(%):扫描索引的叶级页时返回的出错页的百分比。此数与堆无关。对于出错页,分配给索引的下一个物理页不是由当前叶级页中的“下一页”指针所指向的页。
区扫描碎片(%):扫描索引的叶级页时出错区所占的百分比。此数与堆无关。对于出错区,包含当前索引页的区在物理上不是包含上一个索引页的区的下一个区。注意: 如果索引跨越多个文件,则此数字无意义。
avg_page_space_used_in_percent:平均page空间使用率。相关的概念:页拆分、页填充率
avg_fragment_size_in_pages:平均多少个page就有一个碎片,该值 越大越好
avg_fragmentation_in_percent:碎片率,不解释。该值越小越好,和avg_fragment_size_in_pages 反比!
page_count:扫描的总page数
record_count:扫描的总记录数。注意:是相对于当前的扫描来说的记录数,不一定是你所认为的 用户表的一行数据
forwarded_record_count:页拆分的记录数目
3.维护方法
1、删除索引并重建。
2、使用DROP_EXISTING语句重建索引。
3、使用ALTER INDEX REBUILD重新生成索引。(推荐)
4、使用ALTER INDEX REORGANIZE重新组织索引。(推荐)
4.注意事项
碎片率 | 采用方法 |
---|---|
>30% | ALTER INDEX REBUILD WITH(ONLINE = ON) |
>5% 且 <=30% | ALTER INDEX REORGANIZE |
重新生成索引可以联机执行,也可以脱机执行。
重新组织索引始终联机执行。这些值提供了一个大致指导原则,用于确定应在ALTER INDEX REORGANIZE和ALTER INDEX REBUILD之间进行切换的点。不过,实际值可能会随情况而变化,必须要通过试验来确定最适合您环境的阈值。
非常低的碎片级别(小于5%)不应通过这些命令来解决,因为删除如此少量的碎片所获得的收益始终远低于重新生成或重新组织索引的开销。
切记:所有索引碎片维护一定要在凌晨(非业务高峰期间)进行!!!
三、优化指导原则
1.如何知道是否发生了索引碎片?
在SQL Server数据库中,可以通过DBCC SHOWCONTIG WITH ALL_INDEXES或DBCC SHOWCONTIG(表ID或者表名) WITH ALL_INDEXES来检查索引碎片情况
-- 方法一
-- 目标数据库
USE DB_NAME
-- 创建变量指定要查看的表
DECLARE @TABLE_ID INT
SET @TABLE_ID=OBJECT_ID('TABLE_NAME')
-- 执行
DBCC SHOWCONTIG(@TABLE_ID) WITH ALL_INDEXES
-- 方法二
USE DB_NAME
DBCC SHOWCONTIG('TABLE_NAME') WITH ALL_INDEXES
2.索引碎片判断标准
USE DB_NAME
DBCC SHOWCONTIG('TABLE_NAME') WITH ALL_INDEXES
通过对逻辑扫描碎片(过高)、平均页密度(满)(过低)的结果分析,判定是否需要进行索引处理,如下所示:
逻辑扫描碎片 ..................:97.83% 该百分比应该在0%到10%之间,高了则说明有外部碎片。
平均页密度(满) ..................:62.42% 该百分比应该尽可能靠近100%,低了则说明有外部碎片
DBCC SHOWCONTIG 正在扫描 'FundAccountMoneyFlow' 表...
表: 'FundAccountMoneyFlow' (1957582012);索引 ID: 0,数据库 ID: 29
已执行 TABLE 级别的扫描。
- 扫描页数................................: 26485
- 扫描区数..............................: 3312
- 区切换次数..............................: 3311
- 每个区的平均页数........................: 8.0
- 扫描密度 [最佳计数:实际计数].......: 99.97% [3311:3312]
- 区扫描碎片 ..................: 63.53%
- 每页的平均可用字节数.....................: 375.9
- 平均页密度(满).....................: 95.36%
四、优化实践
手动方式
第一步:查询数据库所有表的索引信息
use DB_name
SELECT OBJECT_NAME(B.OBJECT_ID) 表名,B.NAME 索引名称,A.INDEX_TYPE_DESC 索引类型,
ROUND(A.AVG_FRAGMENTATION_IN_PERCENT,2) 碎片率
FROM sys.dm_db_index_physical_stats(DB_ID(), NULL, NULL, NULL, NULL) A
INNER JOIN sys.indexes B ON A.OBJECT_ID=B.OBJECT_ID AND A.INDEX_ID=B.INDEX_ID
WHERE 1=1
AND A.AVG_FRAGMENTATION_IN_PERCENT>30
--AND A.AVG_FRAGMENTATION_IN_PERCENT>5 AND A.AVG_FRAGMENTATION_IN_PERCENT<=30
ORDER BY OBJECT_NAME(B.OBJECT_ID),A.AVG_FRAGMENTATION_IN_PERCENT DESC
注:通过碎片率,依4、注意事项处理方式,也可以逐个对表的索引进行对应的重新生成或重新组织处理
第二步:生成数据库所有表的索引处理的SQL语句
use DB_name
SELECT OBJECT_SCHEMA_NAME(B.OBJECT_ID) 架构,OBJECT_NAME(B.OBJECT_ID) 表名,B.NAME 索引名,ROUND(A.AVG_FRAGMENTATION_IN_PERCENT,2) 碎片率,
CASE WHEN A.AVG_FRAGMENTATION_IN_PERCENT>30 THEN N'重新生成索引' ELSE N'重新组织索引' END 处理方式,
'ALTER INDEX '+QUOTENAME(B.NAME)+' ON '+QUOTENAME(OBJECT_SCHEMA_NAME(B.OBJECT_ID))+'.'+QUOTENAME(OBJECT_NAME(B.OBJECT_ID))+' '
+CASE WHEN A.AVG_FRAGMENTATION_IN_PERCENT>30 THEN 'REBUILD' ELSE 'REORGANIZE' END 生成SQL语句
FROM sys.dm_db_index_physical_stats(DB_ID(),NULL,NULL,NULL,NULL) A INNER JOIN sys.indexes B ON A.OBJECT_ID=B.OBJECT_ID AND A.INDEX_ID=B.INDEX_ID
WHERE A.AVG_FRAGMENTATION_IN_PERCENT>5 AND B.INDEX_ID>0
-- AND OBJECT_NAME(B.OBJECT_ID) IN ('dept') --指定表
ORDER BY CASE WHEN A.AVG_FRAGMENTATION_IN_PERCENT>30 THEN N'重新生成索引' ELSE N'重新组织索引' END,OBJECT_NAME(B.OBJECT_ID),B.INDEX_ID
重新创建索引
有点小问题
use DB_NAME
set nocount on
--使用游标重新组织指定库中的索引,消除索引碎片
--R_T层游标取出当前数据库所有表
declare R_T cursor
for select name from sys.tables
declare @T varchar(50)
open r_t
fetch next from r_t into @t
while @@fetch_status=0
begin
--R_index游标判断指定表索引碎片情况并优化
declare R_Index cursor
for select t.name,i.name,s.avg_fragmentation_in_percent from sys.tables t
join sys.indexes i on i.object_id=t.object_id
join sys.dm_db_index_physical_stats(db_id(),object_id(@T),null,null,'limited') s
on s.object_id=i.object_id and s.index_id=i.index_id
declare @TName varchar(50),@IName varchar(50),@avg int,@str varchar(500)
open r_index
fetch next from r_index into @TName,@Iname,@avg
while @@fetch_status=0
begin
if @avg>=30 --如果碎片大于30,重建索引
begin
set @str='alter index '+rtrim(@Iname)+' on dbo.'+quotename(rtrim(@tname))+' rebuild'
end
else --如果碎片小于30,重新组织索引
begin
set @STR='alter index '+rtrim(@Iname)+' on dbo.'+quotename(rtrim(@tname))+' reorganize'
end
print @str
exec (@str) --执行
fetch next from r_index into @TName,@Iname,@avg
end
--结束r_index游标
close r_index
deallocate r_index
fetch next from r_t into @t
end
--结束R_T游标
close r_t
deallocate r_t
set nocount off
自动方式
第一步:在服务中启动SQL Server 代理
第二步:点击"管理"->右键"维护计划"->"新建维护计划"
第三步:起个名字,点击"确定"
第四步:点击左侧"工具箱",将"重新生成索引"及"重新组织索引"拖至右边区域
第五步:分别对着"重新生成索引"及"重新组织索引"点击右键->"编辑"->在"数据库"项勾选要处理的数据库->点击"确定"
第六步:点击"新建作业计划"按钮->设置频率及执行时间->点击"确定"
第七步:点击"保存选定项"即可
更新统计信息
作用:UPDATE STATISTICS更新统计信息来提高查询效率。建议放在索引碎片计划任务执行完成之后进行
查看:查看某个表的统计信息,可以在SSMS下面查看
执行:
--方法一:UPDATE STATISTICS 表名
UPDATE STATISTICS INVMB
--方法二:执行存储过程SP_UPDATESTATS(更新所有表)
EXEC sp_updatestats
标签:stats,OBJECT,扫描,碎片,索引,维护,ID From: https://www.cnblogs.com/hsuing/p/17337553.html建议不要过于频繁地执行重新生成、重新组织索引以及更新统计信息。另外需要补充的是,非常低数据量与非常低碎片级别一样,通过这些命令来解决,效果甚微