SQL Server数据库查询速度慢的原因有很多,常见的有以下几种:
在镇原等地区,都构建了全面的区域性战略布局,加强发展的系统性、市场前瞻性、产品创新能力,以专注、极致的服务理念,为客户提供成都网站制作、成都网站建设 网站设计制作按需定制制作,公司网站建设,企业网站建设,品牌网站制作,全网营销推广,成都外贸网站建设,镇原网站建设费用合理。
1、没有索引或者没有用到索引(这是查询慢最常见的问题,是数据库设计的缺陷)
2、I/O吞吐量小,形成了瓶颈效应。
3、没有创建计算列导致查询不优化。
4、内存不足
5、网络速度慢
6、查询出的数据量过大(可以采用多次查询,其他的方法降低数据量)
7、锁或者死锁(这也是查询慢最常见的问题,是程序设计的缺陷)
8、sp_lock,sp_who,活动的用户查看,原因是读写竞争资源。
9、返回了不必要的行和列
10、查询语句不好,没有优化
SQLServer性能监控
这套性能优化的清单将至少准科学的帮助你找出你的SQLServer任何明显的性能问题。说是这样说,SQLServer的性能调优仍然是很困难的。我试图用这套清单去找出“容易”的sqlserver性能问题,困难的留待稍后。我这样做是因为很容易将容易和困难的的性能调优问题搞混。通过列出一个“容易”的性能调优范围,就很容易的将这些问题解决,一旦解决了这些容易的问题,那么你就能集中去解决更困难的问题。
使用这个SQLServer性能调优清单的一个好处是,它将不仅仅告诉你目前最容易解决的性能问题是什么,而且还帮助你正确的去解决。在某种程度上,你可以选择不同的顺序进行。换句话说,你可以故意做出特殊的决定而不是按照清单通常的顺序进行。某种意义上说你是对的,不是所有的性能调优建议都适合所有的情形。另外,你的决定是基于你的资源限制,例如没有足够的钱去买满足负荷的硬件。如果真是那样的话,你就别无选择了。还有,你的决定可能基于一些政治原因,那是你不得不作出的改变。不管怎样,你需要知道你能做什么,使用这个性能调优清单找出你能改变的范围并做出相应的改变提升你的SQLServer的性能。
一般来说,你将在你的每一个SQL服务器上执行这个清单。如果遇到清单中的一些问题,这会花掉你一些时间。我建议你从目前性能问题最多的的服务器开始,然后当你有时间的时候按照自己的思路去解决其他服务器。
一旦你完成了,可仍然有很多事情要去做。记住,这些只是一些容易的。一旦你完成了这些容易的,接下来你需要花时间去解决更困难问题。这个是另一篇文章要解决的问题了。
怎样进行你的SQLServer性能调优呢?
为了使其变得容易,我把它们分成了以下几个部分:
? 使用性能监视器找出硬件瓶颈
? SQLServer硬件性能监控列表
? 操作系统性能监控列表
? SQLServer2000配置性能监控列表
? 数据库配置设置性能监控列表
? 索引性能监控列表
? 应用程序和T-SQL性能监控列表
? SQLServer数据库作业性能监控列表
? 使用Profiler找出低效的查询
? 怎样最好的实现SQLServer性能监控
管理你的SQLServe性能的最好方法是首先回顾上面每一部分的内容,把它们打印出来。然后完成每一部分的内容,写下你收集到的结果。你也可以按照你喜欢的顺序进行。上面的步骤仅仅列出了我执行的顺序,因为那样通常能达到一个比较好的效果。
性能监控列表
计数器名称 均值 最小值 最大值
Memory: Pages/sec
Memory: Available Bytes
Physical Disk: % Disk time
Physical Disk: Avg. Disk Queue Length
Processor: % Processor Time
System: Processor Queue Length
SQL Server Buffer: Buffer Cache Hit Ratio
SQL Server General: User Connections
在上表输入你的结果.
使用性能监视器找出SQLServer硬件瓶颈
开始SQLServer性能调优的最佳地方就是从性能监视器(系统监视器)开始。通过一个24小时的周期对一些关键的计数器进行监控,你将对你SQLServer服务器的硬件瓶颈了如指掌。
一般来说,使用性能监视器去创建一个一些关键的计数器的24小时周期的监控日志。当你决定创建这个日志的时候,你需要选择一个典型的24小时的周期,例如,选择一个典型的比较忙的日期,而不是周日或节假日。
一旦你将这些捕获的数据形成日志后,在性能监视器的图形界面下会显示计数器的推荐值。你在上表中记下均值、最小值、峰值。做完这些后,用你的结果跟下面的分析比较。通过你的结果和下面的建议值进行比较,你将能快速的找到你的SQLServe正在经历的潜在的硬件瓶颈。
关键性能计数器说明
下面是不同关键性能计数器的一个讨论,它们的建议值和为了帮助解决硬件瓶颈问题的一些选项。注意我已经限制了性能监视器需要监视的一些关键计数器。我这么做是因为在本文我们的目的是为了容易的找到显而易见的性能问题,许多其他的性能监视器计数器你能在本网站其他地方找到。
Memory: Pages/sec
这个计数器记录的是每秒钟内存和磁盘之间交换的页面数。交换更多的页面、超过你服务器承受的更多的I/O,将轮流降低你SQLserver的性能。你的目的就是尽量将页面减少到最小,而不是消除它。
如果你的服务器上SQLServer是最主要的应用程序,那么这个值的理想范围是0~20之间。可能很多时候你看到的值都会超过20。这个值一般要保持在每秒的平均页数在20以下。
如果这个值平均总是超过20,其中最大的一个可能是内存瓶颈问题,需要增加内存。通常来说,更多的内存意味着需要执行的页面更少。
在大多数情况下,服务器决定SQLServer使用的适当内存的大小,页面将平均小于20。给SQLServer适当的内存意味着服务器的缓存命中率(Buffer Hit Cache Ratio 这个稍后会讲到)达到99%或者更高。如果在一个24小时的周期里你的sqlserver的缓存命中率达到99%或者更高,但是在这个期间你的页面数总是超过20,这意味着你或许运行了其他的程序。如果是这样的情况,建议你移除这些程序,使SQLServer是你的服务器的最主要的程序。
如果你的sqlserver服务器没有运行其他程序,并且在一个24小时的周期里页面数总是超过20,这说明你应该修改你对SQLServer的内存设置了。将其设置为“动态配置SQLServer的内存”,并且最大内存设置得高一些。为了达到最优,SQLServer将尽可能的获得多的内存以完成自己的工作,而不是去和其他的程序争夺内存。
Memory: Available Bytes
另一个检查SQLServer是否有足够的物理内存的方法是检查Memory Object: Available Bytes计数器。 这个值至少大于5M,否则需要添加更多的物理内存。在一个专门的SQLServer服务器上,SQLServer试图维持4-10M的自由物理内存,其余的物理内存被操作系统和SQLServer使用。当可用的物理内存接近5M或者更低时,SQLServer最可能因为缺少内存而遇到性能瓶颈。遇此情况,你需要增加物理内存以减少服务器的负荷,或者给SQLServer配置一个合适的内存。
Physical Disk: % Disk Time
这个计数器度量磁盘阵列繁忙程度(不是逻辑分区或磁盘阵列上独立的磁盘)。它提供一个对磁盘阵列繁忙程度相对较好的度量。原则上计数器% Disk Time的值应该小于55%。如果持续超过55%(在你24小时的监控周期里大约超过10分钟),说明你的SQLServer有I/O瓶颈。如果你只是偶尔看到,也不必太担心。但是,如果经常发生的话(也就是说,一个小时出现好几次),就应该着手寻找增加服务器I/O性能或者减少服务器负荷的解决之道了。一般是为磁盘阵列增加磁盘,或者更好更快的磁盘,或者给控制器卡增加缓存,或者使用不同版本的RAID,或者更换更快的控制器。
在NT4.0上使用该计数器之前,确认在NT命令提示符下输入diskperf -y,重启服务器,以便手动打开。在NT4.0下第一次必须将该计数器打开,Windows2000默认是打开的。
Physical Disk: Avg. Disk Queue Length
除了观察物理磁盘的% Disk Time计数器外,还可以用Avg. Disk Queue Length计数器。磁盘阵列中的各个磁盘的该值如果超过2(在你24小时的监控周期里大约超过10分钟),那么你的磁盘阵列存在I/O瓶颈问题。象计数器% Disk Time一样,如果只是偶尔看到,也不必太担心。但是,如果经常发生的话,就应该着手寻找增加服务器I/O性能的解决之道了。如前所述。
你需要计算这个值,因为性能监视器不知道你的磁盘阵列中有多少物理磁盘。例如,如果你有一个6个物理磁盘组成的磁盘阵列,它的Avg.
Disk Queue Length值为10,那么实际每个磁盘的值为1.66(10/6=1.66),它们都在建议值2以内。
在NT4.0上使用该计数器之前,确认在NT命令提示符下输入diskperf -y,重启服务器,以便手动打开。在NT4.0下第一次必须将该计数器打开,Windows2000默认是打开的。
一起使用这两个计数器将帮助你找出I/O瓶颈。例如,如果% Disk Time的值超过55%,Avg. Disk Queue Length计数器值超过2,服务器则存在I/O瓶颈。
Processor: % Processor Time
处理器对象: % Processor Time计数器对每一个CPU可用,并针对每一个CPU进行检测。同样对于所有的CPU也可用。这是一个观察CPU利用率的关键计数器。如果% Total Processor Time计数器的值持续超过80%(在你24小时的监控周期里大约超过10分钟),说明CPU存在瓶颈问题。如果只是偶尔发生,并且你认为对你的服务器影响不大,那没问题。如果经常发生,你应该减少服务器的负载,更换更高频率的CPU,或者增加CPU的数量或者增加CPU的2级缓存(L2 cache)。
System: Processor Queue Length
根据% Processor Time计数器,你可以监控Processor Queue Length计数器。每个CPU的该值如果持续超过2(在你24小时的监控周期里大约超过10分钟),那么你的CPU存在瓶颈问题。例如,如果你的服务器有4个CPU,Processor Queue Length计数器的值总共不应超过8。
如果Processor Queue Length计数器的值有规律的超过建议的最大值,但是CPU利用率相对不是很高,那么考虑减少SQLServer的"max worker threads"的配置值。Processor Queue Length计数器的值高的可能原因是有太多的工作线程等待处理。通过减少"maximum worker threads"的值,强迫线程池踢掉某些线程,从而使线程池得到最大的利用。
一起使用计数器Processor Queue Length和计数器% Total Process Time,你可以找到CPU瓶颈,如果都显示超过它们的建议值,可以确信存在CPU瓶颈问题。
SQL Server Buffer: Buffer Cache Hit Ratio
SQL Server Buffer中的计数器Buffer Cache Hit Ratio用来指出SQLServer从缓存中而不是磁盘中获得数据的频率。在一个OLTP程序中,该比率应该超过90%,理想值是超过99%。如果你的buffer cache hit ratio低于90%,你需要立即增加内存。如果该比率在90%和99%之间,你应该认真考虑购买更多的内存了。如果接近99%,你的SQLServer性能是比较快的了。某些情况下,如果你的数据库非常大,你不可能达到99%,即使你在服务器上配置了最大的内存。你所能做的就是尽可能的添加内存。
在OLAP程序中,由于其本身的工作原理,该比率大大减少。不管怎样,更多的内存总是能提高SQLServer的性能。
SQL Server General: User Connections
既然sqlserver的使用人数会影响它的性能,你就需要专注于sqlserver的General Statistics Object: User Connections计数器。它显示sqlserver目前连接的数量,而不是用户数。
如果该计数器超过255,那么你需要将sqlserver的"Maximum Worker Threads" 的配置值设置得比缺省值255高。如果连接的数量超过可用的线程数,那么sqlserver将共享线程,这样会影响性能。"Maximum Worker Threads"需要设置得比你服务器曾经达到的最大连接数更高。
MySQL的优点:
1. 它使用的核心线程是完全多线程,支持多处理器。
2. 有多种列类型:1、2、3、4、和8字节长度自有符号/无符号整数、FLOAT、DOUBLE、CHAR、VARCHAR、TEXT、BLOB、DATE、TIME、DATETIME、 TIMESTAMP、YEAR、和ENUM类型。
3. 它通过一个高度优化的类库实现SQL函数库并像他们能达到的一样快速,通常在查询初始化后不该有任何内存分配。没有内存漏洞。
4. 全面支持SQL的GROUP BY和ORDER BY子句,支持聚合函数(COUNT()、COUNT(DISTINCT)、AVG()、STD()、SUM()、MAX()和MIN())。你可以在同一查询中混来自不同数据库的表。
5. 支持ANSI SQL的LEFT 0UTER JOIN和ODBC。
6. 所有列都有缺省值。你可以用INSERT插入一个表列的子集,那些没用明确给定值的列设置为他们的决省值。
7. MySQL可以工作在不同的平台上。支持C、C++、Java、Perl、PHP、Python和TCL API。
(2) MySQL的缺点:
1、 MySQL最大的缺点是其安全系统,主要是复杂而非标准,另外只有到调用mysqladmin来重读用户权限时才发生改变。
2、 MySQL的另一个主要的缺陷之一是缺乏标准的RI(Referential Integrity-RI)机制;Rl限制的缺乏(在给定字段域上的一种固定的范围限制)可以通过大量的数据类型来补偿。
3、 MySQL没有一种存储过程(Stored Procedure)语言,这是对习惯于企业级数据库的程序员的最大限制。
4、 MySQL不支持热备份。
5、 MySQL的价格随平台和安装方式变化。Linux的MySQL如果由用户自己或系统管理员而不是第三方安装则是免费的,第三方案则必须付许可费。Unix或Linux 自行安装 免费 、Unix或Linux 第三方安装 200美元,
SQL Server的优点众多,但是Microsoft SQL Server和其他数据库产品相比也存在着以下劣势:
1开放性。只能运行在微软的windows平台,没有丝毫的开放性可言。
2可伸缩性,并行性。并行实施和共存模型并不成熟,很难处理日益增多的用户数和数据卷,伸缩性有限。
3性能稳定性。SQLServer当用户连接多时性能会变的很差,并且不够稳定。
4使用风险。SQLServer完全重写的代码,经历了长期的测试,不断延迟,许多功能需时间来证明。并不十分兼容早期产品。使用需要冒一定风险。
5客户端支持及应用模式。只支持C/S模式。
毫无疑问,给表添加索引是有好处的,你要做的大部分工作就是维护索引,在数据更改期间索引可能产生碎片,所以一些维护是必要的。碎片可能是你查询产生性能问题的来源。
那么到底什么是索引碎片呢?索引碎片实际上有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比其他方法的确有好处的是在其他过程访问索引时也能进行碎片整理,不会引起其他方法的阻塞问题。