问答文章1 问答文章501 问答文章1001 问答文章1501 问答文章2001 问答文章2501 问答文章3001 问答文章3501 问答文章4001 问答文章4501 问答文章5001 问答文章5501 问答文章6001 问答文章6501 问答文章7001 问答文章7501 问答文章8001 问答文章8501 问答文章9001 问答文章9501

sqlserver索引碎片怎么避免

发布网友 发布时间:2022-04-30 20:15

我来回答

2个回答

懂视网 时间:2022-04-10 05:10

%,于是开始对这个表进行重点跟踪和记录日志。今天用DBCC SHOWCONTIG WITH TABLERESULTS 命令检查了一下所有表的概况,然后参照着MSDN对字段的说明,发现问题比较严重。ScanDensity(这是“最佳计数”与“实际计数”的比率。如果所有内容都是连续的,则该值为 100;如果该值小于 100,则存在一些碎片)有的甚至在16.6666666666667,其他扫描密度等指标也特别不理想。 检查: 随便贴出一个表的扫描结果: -------------------------------------------------------------------------------------------------------------------------- DBCC SHOWCONTIG 正在扫描 ‘UserInfo‘ 表... 表: ‘UserInfo‘ (1646628909);索引 ID: 1,数据库 ID: 7 已执行 TABLE 级别的扫描。 - 扫描页数................................: 367 - 扫描区数..............................: 48 - 区切换次数..............................: 355 - 每个区的平均页数........................: 7.6 - 扫描密度 [最佳计数:实际计数].......: 12.92% [46:356] - 逻辑扫描碎片 ..................: 95.37% - 区扫描碎片 ..................: 47.92% - 每页的平均可用字节数.....................: 2996.8 - 平均页密度(满).....................: 62.98% DBCC 执行完毕。如果 DBCC 输出了错误信息,请与系统管理员联系。 -------------------------------------------------------------------------------------------------------------------------- 解释如下( 查看解释来源点此 ,MSDN解释太官方,还是用简单点的话来解释): 扫描页数:如果你知道行的近似尺寸和表或索引里的行数,那么你可以估计出索引里的页数。看看扫描页数,如果明显比你估计的页数要高,说明存在内部碎片。 扫描扩展盘区数:用扫描页数除以8,四舍五入到下一个最高值。该值应该和DBCC SHOWCONTIG返回的扫描扩展盘区数一致。如果DBCC SHOWCONTIG返回的数高,说明存在外部碎片。碎片的严重程度依赖于刚才显示的值比估计值高多少。 扩展盘区开关数:该数应该等于扫描扩展盘区数减1。高了则说明有外部碎片。 每个扩展盘区上的平均页数:该数是扫描页数除以扫描扩展盘区数,一般是8。小于8说明有外部碎片。 扫描密度[最佳值:实际值]:DBCC SHOWCONTIG返回最有用的一个百分比。这是扩展盘区的最佳值和实际值的比率。该百分比应该尽可能靠近100%。低了则说明有外部碎片。 逻辑扫描碎片:无序页的百分比。该百分比应该在0%到10%之间,高了则说明有外部碎片。 扩展盘区扫描碎片:无序扩展盘区在扫描索引叶级页中所占的百分比。该百分比应该是0%,高了则说明有外部碎片。 每页上的平均可用字节数:所扫描的页上的平均可用字节数。越高说明有内部碎片,不过在你用这个数字决定是否有内部碎片之前,应该考虑fill factor(填充因子)。 平均页密度(完整):每页上的平均可用字节数的百分比的相反数。低的百分比说明有内部碎片。 整理数据库碎片索引 看到如此不对劲,果断去MSDN查找相关资料,找到了MSDN有对数据库索引进行碎片整理的T-SQL,执行了一下,发现效果还不错。 使用 DBCC SHOWCONTIG 和 DBCC INDEXDEFRAG 对数据库中的索引进行碎片整理:(以下示例将展示一种简单的方法,对数据库中碎片数量在声明的阈值之上的所有索引进行碎片整理。) /*Perform a ‘USE <database name>‘ to select the database in which to run the script.*/ -- Declare variables SET NOCOUNT ON; DECLARE @tablename varchar(255); DECLARE @execstr varchar(400); DECLARE @objectid int; DECLARE @indexid int; DECLARE @frag decimal; DECLARE @maxfrag decimal; -- Decide on the maximum fragmentation to allow for. SELECT @maxfrag = 30.0; -- Declare a cursor. DECLARE tables CURSOR FOR SELECT TABLE_SCHEMA + ‘.‘ + TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = ‘BASE TABLE‘; -- Create the table. CREATE TABLE #fraglist ( ObjectName char(255), ObjectId int, IndexName char(255), IndexId int, Lvl int, CountPages int, CountRows int, MinRecSize int, MaxRecSize int, AvgRecSize int, ForRecCount int, Extents int, ExtentSwitches int, AvgFreeBytes int, AvgPageDensity int, ScanDensity decimal, BestCount int, ActualCount int, LogicalFrag decimal, ExtentFrag decimal); -- Open the cursor. OPEN tables; -- Loop through all the tables in the database. FETCH NEXT FROM tables INTO @tablename; WHILE @@FETCH_STATUS = 0 BEGIN; -- Do the showcontig of all indexes of the table INSERT INTO #fraglist EXEC (‘DBCC SHOWCONTIG (‘‘‘ + @tablename + ‘‘‘) WITH FAST, TABLERESULTS, ALL_INDEXES, NO_INFOMSGS‘); FETCH NEXT FROM tables INTO @tablename; END; -- Close and deallocate the cursor. CLOSE tables; DEALLOCATE tables; -- Declare the cursor for the list of indexes to be defragged. DECLARE indexes CURSOR FOR SELECT ObjectName, ObjectId, IndexId, LogicalFrag FROM #fraglist WHERE LogicalFrag >= @maxfrag AND INDEXPROPERTY (ObjectId, IndexName, ‘IndexDepth‘) > 0; -- Open the cursor. OPEN indexes; -- Loop through the indexes. FETCH NEXT FROM indexes INTO @tablename, @objectid, @indexid, @frag; WHILE @@FETCH_STATUS = 0 BEGIN; PRINT ‘Executing DBCC INDEXDEFRAG (0, ‘ + RTRIM(@tablename) + ‘, ‘ + RTRIM(@indexid) + ‘) - fragmentation currently ‘ + RTRIM(CONVERT(varchar(15),@frag)) + ‘%‘; SELECT @execstr = ‘DBCC INDEXDEFRAG (0, ‘ + RTRIM(@objectid) + ‘, ‘ + RTRIM(@indexid) + ‘)‘; EXEC (@execstr); FETCH NEXT FROM indexes INTO @tablename, @objectid, @indexid, @frag; END; -- Close and deallocate the cursor. CLOSE indexes; DEALLOCATE indexes; -- Delete the temporary table. DROP TABLE #fraglist; GO 执行后会返回索引扫描数、移动数、删除数(Pages Scanned、Pages Moved、Pages Removed)。效果还是很明显的,然后再把扫描结果进行比对: ----------------------------------------------------------------------------------------------------------------- DBCC SHOWCONTIG 正在扫描 ‘UserInfo‘ 表... 表: ‘UserInfo‘ (1646628909);索引 ID: 1,数据库 ID: 7 已执行 TABLE 级别的扫描。 - 扫描页数................................: 237 - 扫描区数..............................: 31 - 区切换次数..............................: 30 - 每个区的平均页数........................: 7.6 - 扫描密度 [最佳计数:实际计数].......: 96.77% [30:31] - 逻辑扫描碎片 ..................: 2.95% - 区扫描碎片 ..................: 29.03% - 每页的平均可用字节数.....................: 200.3 - 平均页密度(满).....................: 97.52% DBCC 执行完毕。如果 DBCC 输出了错误信息,请与系统管理员联系 ------------------------------------------------------------------------------------------------------------ 结果很有对比性,碎片大幅降低,每页的平均可用字节数大幅降低,扫描密度提高,平均页密度达到理想中的近饱和数值。看来DBCC的一些命令和MSDN的联机丛书还是很不错滴。虽然暂时降低了一些碎片指标,但只要有操作肯定也会有碎片产生,通过一段的时间跟踪,才能对整体情况进行主观的判断。 相关链接:http://msdn.microsoft.com/zh-cn/library/ms188796.aspx http://msdn.microsoft.com/zh-cn/library/ms175008(v=sql.90).aspx

 

通过DBCC整理Sqlserver数据库表索引碎片

标签:print   扫描   end   exe   extent   style   ase   result   cal   

热心网友 时间:2022-04-10 02:18

毫无疑问,给表添加索引是有好处的,你要做的大部分工作就是维护索引,在数据更改期间索引可能产生碎片,所以一些维护是必要的。碎片可能是你查询产生性能问题的来源。

那么到底什么是索引碎片呢?索引碎片实际上有2种形式:外部碎片和内部碎片。不管哪种碎片基本上都会影响索引内页的使用。这也许是因为页的逻辑顺序错误(即外部碎片)或每页存储的数据量少于数据页的容量(内部错误)。无论索引产生了哪种类型的碎片,你都会因为它而面临查询的性能问题。

外部碎片

当 索引页不在逻辑顺序上时就会产生外部碎片。索引创建时,索引键按照逻辑顺序放在一组索引页上。当新数据插入索引时,新的键可能放在存在的键之间。为了让新 的键按照正确的顺序插入,可能会创建新的索引页来存储需要移动的那些存在的键。这些新的索引页通常物理上不会和那些被移动的键原来所在的页相邻。创建新页 的过程会引起索引页偏离逻辑顺序。

下面的例子将比实际的言论更加清晰的解释这个概念。
假定在任何另外的数据插入你的表之前存在索引上的结构如下

(注:下面图片里应该是7和8,原文里是6和8):

INSERT语句往索引里添加新的数据,假定添加的是5。INSERT将引起新页创建,为了给5在原来的页上留出空间,7和8被移到了新页上。这个创建将引起索引页偏离逻辑顺序。

在有特定搜索或者返回无序结果集的查询的情况下,偏离顺序的索引页不会引起问题。对于返回有序结果集的查询,搜索那些无序的索引页需要进行额外的处理。有序结果集的例子如查询返回4到10之间的记录。为了返回7和8,查询不得不进行额外的页切换。虽然一个额外的页切换在一个长时间运行里是无关紧要的,然而想象一下一个有好几百页偏离顺序的非常大的表的情形。

内部碎片

当索引页没有用到最大量时就产生了内部碎片。虽然在一个有频繁数据插入的应用程序里这也许有帮助,然而设置一个fill factor(填充因子)会在索引页上留下空间,服务器内部碎片会导致索引尺寸增加,从而在返回需要的数据时要执行额外的读操作。这些额外的读操作会降低查询的性能。

怎样确定索引是否有碎片?

SQLServer提供了一个数据库命令――DBCC SHOWCONTIG――来确定一个指定的表或索引是否有碎片。
DBCC SHOWCONTIG
数据库平台命令,用来显示指定的表的数据和索引的碎片信息。

DBCC SHOWCONTIG 权限默认授予 sysadmin固定服务器角色或 db_owner 和 db_ddladmin固定数据库角色的成员以及表的所有者且不可转让。
语法(SQLServer2000)

DBCC SHOWCONTIG
[ ( { table_name | table_id| view_name | view_id }
[ , index_name | index_id ]
)
]
[ WITH { ALL_INDEXES
| FAST [ , ALL_INDEXES ]
| TABLERESULTS [ , { ALL_INDEXES } ]
[ , { FAST | ALL_LEVELS } ]
}
]

语法(SQLServer7.0)

DBCC SHOWCONTIG
[ ( table_id [,index_id ]
)
]

示例:
显示数据库里所有索引的碎片信息
SET NOCOUNT ON
USE pubs
DBCC SHOWCONTIG WITH ALL_INDEXES

GO

显示指定表的所有索引的碎片信息
SET NOCOUNT ONUSE pubs
DBCC SHOWCONTIG (authors) WITH ALL_INDEXES
GO

显示指定索引的碎片信息
SET NOCOUNT ON
USE pubs
DBCC SHOWCONTIG (authors,aunmind)
GO

结果集
DBCC SHOWCONTIG将返回扫描页数、扫描扩展盘区数、遍历索引或表的页时,DBCC 语句从一个扩展盘区移动到其它扩展盘区的次数、每个扩展盘区的页数、扫描密度(最佳值是指在一切都连续地链接的情况下,扩展盘区更改的理想数目)。

DBCC SHOWCONTIG 正在扫描 'authors' 表...
表: 'authors'(1977058079);
索引 ID: 1,数据库 ID: 5
已执行 TABLE 级别的扫描。
- 扫描页数.....................................: 1
- 扫描扩展盘区数...............................: 1
- 扩展盘区开关数...............................: 0
- 每个扩展盘区上的平均页数.....................: 1.0
- 扫描密度[最佳值:实际值]....................: 100.00%[1:1]
- 逻辑扫描碎片.................................: 0.00%
- 扩展盘区扫描碎片.............................: 0.00%
- 每页上的平均可用字节数.......................: 6010.0
- 平均页密度(完整)...........................: 25.75%
DBCC 执行完毕。如果 DBCC 输出了错误信息,请与系统管理员联系。
 

寻找什么

扫描页数:如果你知道行的近似尺寸和表或索引里的行数,那么你可以估计出索引里的页数。看看扫描页数,如果明显比你估计的页数要高,说明存在内部碎片。

扫描扩展盘区数:用扫描页数除以8,四舍五入到下一个最高值。该值应该和DBCC SHOWCONTIG返回的扫描扩展盘区数一致。如果DBCC SHOWCONTIG返回的数高,说明存在外部碎片。碎片的严重程度依赖于刚才显示的值比估计值高多少。

扩展盘区开关数:该数应该等于扫描扩展盘区数减1。高了则说明有外部碎片。

每个扩展盘区上的平均页数:该数是扫描页数除以扫描扩展盘区数,一般是8。小于8说明有外部碎片。

扫描密度[最佳值:实际值]:DBCC SHOWCONTIG返回最有用的一个百分比。这是扩展盘区的最佳值和实际值的比率。该百分比应该尽可能靠近100%。低了则说明有外部碎片。

逻辑扫描碎片:无序页的百分比。该百分比应该在0%到10%之间,高了则说明有外部碎片。

扩展盘区扫描碎片:无序扩展盘区在扫描索引叶级页中所占的百分比。该百分比应该是0%,高了则说明有外部碎片。

每页上的平均可用字节数:所扫描的页上的平均可用字节数。越高说明有内部碎片,不过在你用这个数字决定是否有内部碎片之前,应该考虑fill factor(填充因子)。

平均页密度(完整):每页上的平均可用字节数的百分比的相反数。低的百分比说明有内部碎片。

备注

DBCC SHOWCONTIG实际上仅对那些大表有用。小表显示的结果根本不符合正常标准,因为他们也许没有由多于8个的页面组成。你在查看小表上执行DBCC SHOWCONTIG的结果时应该忽略一些结果。在处理小表时只需关心扩展盘区开关数、逻辑扫描碎片、每页上的平均可用字节数、平均页密度(完整)。

DBCC SHOWCONTIG默认输出的结果是:扫描页数、扫描扩展盘区数、扩展盘区开关数、每个扩展盘区上的平均页数、扫描密度[最佳值:实际值]、逻辑扫描碎片、扩展盘区扫描碎片、每页上的平均可用字节数、平均页密度(完整)。可以用FAST和TABLERESULTS选项来控制这个输出结果。

FAST选项指定执行索引的快速扫描,输出结果是最小的,该选项不读索引的叶或数据页且只返回扫描页数、扫描扩展盘区数、扫描密度[最佳值:实际值]、逻辑扫描碎片。

TABLERESULTS选项将用行集的形式显示信息,将返回扩展盘区开关数、扫描密度[最佳值:实际值]、逻辑扫描碎片、扩展盘区扫描碎片、每页上的平均可用字节数、平均页密度(完整)。

如果既指定FAST选项又指定TABLERESULTS选项,那么将返回对象名、对象ID、索引名、索引ID,页数、扩展盘区开关数、扫描密度[最佳值:实际值]和逻辑扫描碎片。

ALL_INDEXES选项将显示指定表和试图的所有索引的结果,即使指定了一个索引。

ALL_LEVELS选项指定是否为所处理的每个索引的每个级别产生输出(默认只输出索引的页级或表数据级的结果),并且只能与 TABLERESULTS 选项一起使用。

解决碎片问题

一旦你确定表或索引有碎片问题,那么你有4个选择去解决那些问题:
删除并重建索引
使用DROP_EXISTING子句重建索引
执行DBCC DBREINDEX
执行DBCC INDEXDEFRAG
尽管每一个技术都能达到你整理索引碎片的最终目的,但各有各的优缺点。

删除并重建索引

用DROP INDEX和CREATE INDEX或ALTER TABLE来 删除并重建索引有些缺陷包括在删除重建期间索引会消失。在索引删除重建时,对于查询它不在可用,查询性能也许会受到明显的影响,直到重建索引为止。另一个 潜在的缺陷是当都请求索引的时候会引起阻塞,直到重建索引为止。通过其他的处理也能解决阻塞,就是索引被使用的时候不删除索引。另一个主要的缺陷是在用DROP INDEX和CREATE INDEX重建聚集索引时会引起非聚集索引重建两次。删除聚集索引时非聚集索引的行指针会指向数据堆,聚集索引重建时非聚集索引的行指针又会指回聚集索引的行位置。

删除并重建索引的确有一个好处就是通过重新排序索引页,使索引页紧凑并删除不需要的索引页来完全重建索引。你也许需要考虑那些内部和外部碎片都很高的情况下才使用,以使那些索引回到它们应该在的位置。

使用DROP_EXISTING子句重建索引

为了避免在重建聚集索引时表上的非聚集索引重建两次,可以使用带DROP_EXISTING子句的CREATE INDEX语句。这个子句会保留聚集索引键值,以避免非聚集索引重建两次。和删除并重建索引一样,该方法也可能会引起阻塞和索引消失的问题。该方法的另一个缺陷是也强迫你去分别发现和修复表上的每一个索引。 除了和上一个方法一样的好处之外,该方法的好处是不必重建非聚集索引两次。这样可以对那些带约束的索引提供正确的索引定义以符合约束的要求。 执行DBCC DBREINDEX DBCC DBREINDEX类似于第二种方法,但它物理地重建索引,允许SQLServer给索引分配新页来减少内部和外部碎片。DBCC DBREINDEX也能动态的重建带约束的索引,不象第二种方法。 DBCC DBREINDEX的缺陷是会遇到或引起阻塞问题。DBCC DBREINDEX是作为一个事务来运行的,所以如果在完成之前中断了,那么你会丢失所有已经执行过的碎片。 执行DBCC INDEXDEFRAG DBCC INDEXDEFRAG(在SQLServer2000中可用)按照索引键的逻辑顺序,通过重新整理索引里存在的叶页来减少外部碎片,通过压缩索引页里的行然后删除那些由此产生的不需要的页来减少内部碎片。它不会遇到阻塞问题但它的结果没有其他几个方法彻底。这是因为DBCC INDEXDEFRAG跳过了锁定的页且不使用任何新页来重新排序索引。如果索引的碎片数量大的话你也许会发现DBCC INDEXDEFRAG比重建索引花费的时间更长。DBCC INDEXDEFRAG比其他方法的确有好处的是在其他过程访问索引时也能进行碎片整理,不会引起其他方法的阻塞问题。
声明声明:本网页内容为用户发布,旨在传播知识,不代表本网认同其观点,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。E-MAIL:11247931@qq.com
药膳是什么意思 药膳有哪些种类 滴滴开通了哪些城市 超高频感应加热设备简介 萌三国魏国的暗金射手哪个好? 萌三国暗金弓箭手哪个好、、、 萌三国暗金武将有哪些? 萌三国30虎符换什么暗金好? 萌三国推荐15个将(红色和暗金)非RMB玩家 萌三国暗金刘备配什么名将技能? 萌三国中暗金武将 能推荐 各类别武将 比较强势的一些 比如战士:XX_百度... 请教SQL里怎样使用碎片整理 SQLSERVER 怎样 加索引 能显著提高速度 java源代码写好后怎么让它执行呢 南京工程学院的软件工程可不可以考研 对口单招上的 南京工程学院 能考研吗 孙燕姿的《离开》怎么卖完了呢? 我想考南京工程学院的研究生,我是南京师范大学中北学院的,电气工程及其自动化的? 我们那里来了一个新同事,卖烟的,她今天盘烟,发现烟少了,烟的总数是46.销量单上是55,少九包, 我是南京工程学院本三自动化专业的学生,想考研。南京工业大学的研究生怎么样? 编写一个java程序的源代码 起亚这款MPV明年国产,韩国市场已夺冠 特斯拉3月在华销量突破1万台 创历史新高 一个企业的销量单位大概在哪个? 在南京工程学院上大学以后考研容易不? 八荣八耻提示语 南京工程学院自动化专业考研 网警在线帮助24小时?你好,在吗?我下午刷京东销量单被骗38000多,怎么办_百度问一问 福州象园永辉超市销量单 党代会宣传标语 为呼吁更多人“学党史,悟思想,办实事,开新局”请设计一句宣传标语。_百度问一问 sqlserver 2000 索引碎片 sqlserver2008 怎么定时清理索引碎片 关于SQLServer 2000 索引问题 sqlserver,表已添加索引,是否仍会随着数据量不断不断增大而查询越来越慢... 解决delete后查询的性能有关问题,怎么清理碎片,降低高水位 sql server cpu使用率过高 字符串索引和数值索引哪个更快 如何突破限制录屏 SQL Server 2016将有哪些功能改进 200数据量的配置表(基本不动,关联比较多),加索引会查询变快吗?_百度... 活青虾出过水两边为什么会变黑? 影响虾子身体颜色的主要原因 如何遍历数据库中某表单的字段名 金立S10是什么处理器,采用高通还是联发科CPU 金立s10的联发科P25能不能换成高通的处理器,比如835 华为p10plus和金立s10哪一个处理器性能好 金立s10和vivox9s那个cpu好 EXCEL中怎么让列号用数字表示而不是用字母??? excel中列的英文字母变成了跟行一样的数字,怎么改过来??我是excel2010的版本,谢谢 在excel表中,正常的行号为数字,列标为英文,而我的表列标为数字,怎么样才能反列标转为英文?请高手赐教 我办理了中国移动的58元无限流量套餐。人工客服说超过10个g之后会限速