我正在 47mb 的 Shairpoint 搜索数据库上运行带有 REPAIR_ALLOW_DATA_LOSS 的 CheckDB
它已经运行了 30 多分钟。这正常吗?
需要多长时间?
答案1
哈 - 这是我最喜欢被问到的(最不喜欢的)问题(就像我写的 DBCC CHECKDB 一样)。
干得好:
只有一次您应该尝试计算 CHECKDB 需要多长时间 - 当您计划定期数据库维护时。如果您面临损坏(或疑似损坏)的数据库,并且您才刚刚开始考虑 CHECKDB 需要多长时间 - 您在规划灾难恢复策略时犯了一个错误。您始终需要知道 CHECKDB 为您的数据库运行(平均)需要多长时间,因此:
- 你可以判断 CHECKDB 的某次运行是否比平时花费的时间更长——这表明它发现了一些损坏
- 您知道在灾难恢复情况下需要多长时间才能获得结果
每次我参加会议,总有人问我 CHECKDB 需要多长时间才能在他们的数据库上运行。我可以用以下几种方式来回答这个问题:
- 没有帮助的答案是——我不知道。
- 几乎有帮助的答案——上次运行花了多长时间,条件完全相同吗?
- 我通常给出的答案是视情况而定。
现在,许多人会认为第三个答案与第一个答案有些相似——毫无帮助。问题是,有许多因素会影响 CHECKDB 的运行时间。让我解释一下最重要的十个因素,这样你就知道为什么这实际上是一个有用的答案。这些因素的重要性没有特定的顺序。
- 数据库的大小 很明显...CHECKDB 必须读取数据库中每个分配的页面,因此页面越大,读取所有页面所需的时间就越长。
- 服务器上的并发 IO 负载 从最简单的层面来说,CHECKDB 要做什么?它会读取数据库中每个已分配的页面。这会产生大量的 IO。CHECKDB 会尽最大努力执行最高效的 IO,并按物理顺序读取数据库页面,并提前进行大量读取,以便磁盘磁头在磁盘上平稳移动(而不是随机跳来跳去并导致磁盘磁头寻道延迟)。如果服务器上没有并发 IO 负载,则 IO 将尽可能高效。但是,从 SQL Server 引入任何额外的 IO 都意味着磁盘磁头会跳来跳去 - 从而降低 CHECKDB 的 IO 速度。如果 IO 子系统已经达到 CHECKDB 的 IO 需求容量,则任何额外的 IO 都会减少 CHECKDB 可用的 IO 带宽 - 从而降低其速度。
- 服务器上的并发 CPU 活动 在下一个简单级别,CHECKDB 将以某种方式处理它读取的每个页面。根据您指定的各种选项和数据库架构(详细信息如下),这将使用大量 CPU - CHECKDB 运行时,服务器的 CPU 可能会达到 100%。如果服务器上有任何额外的工作负载,这将占用 CHECKDB 的 CPU 周期,并使其变慢。基本上,第 2 点和第 3 点说的是 CHECKDB 非常耗费资源!这可能是您可以要求 SQL Server 执行的最耗费资源的事情之一,因此通常最好不要在高峰工作负载时间运行它,因为您不仅会导致 CHECKDB 运行时间更长,还会减慢并发工作负载,可能令人无法接受。
- 数据库上的并发更新活动 这与 SQL 2000 和 SQL 2005 都相关,但原因不同。在 SQL 2000 中,CHECKDB 从并发 DML 事务的事务日志分析中获取数据库的一致视图(有关详细信息,请参阅此处)。CHECKDB 运行时的并发 DML 越多,生成的事务日志就越多 - 因此 CHECKDB 分析该事务日志所需的时间就越长。在一个大型多 CPU 机箱上,如果有大量并发 DML,而 CHECKDB 被限制在单个 CPU 上,则 CHECKDB 的此阶段可能比读取和处理数据库页面的时间长几倍!(我在现实生活中见过几次这种情况。)在 SQL 2005 中,CHECKDB 从数据库快照中获取数据库的一致视图,该快照与数据库本身存储在相同的磁盘卷上。如果 CHECKDB 运行时数据库中发生大量更改,则更改的页面将被推送到快照以保持一致。由于快照文件与数据库文件存储在同一位置,因此每次将页面推送到快照时,磁盘头都必须移动,这会中断 #2 中描述的高效 IO。此外,每当 CHECKDB 读取页面时,它都需要从快照文件而不是数据库文件中读取页面,这又需要一次磁盘头移动和另一次高效 IO 中断。对数据库的并发更改越多,对高效 IO 的中断就越多,CHECKDB 的运行速度就越慢。
- IO 子系统的吞吐能力 这个很简单。CHECKDB 将执行大量的 IO,甚至可能最终受到 IO 限制(这意味着 CPU 会定期空闲以等待 IO 完成),具体取决于指定的选项和数据库模式。这意味着 IO 子系统的吞吐量将直接影响 CHECKDB 的运行时间。因此,如果您有一个 1TB 的数据库,而 IO 子系统只能管理 100MB/秒,那么仅读取数据库就需要将近 3 个小时(1TB/100MB/3600 秒),除了升级 IO 子系统外,您无法加快速度。我已经记不清有多少次听到客户抱怨 CHECKDB(或索引重建或其他 IO 密集型操作)运行缓慢,结果却发现磁盘队列长度巨大,IO 子系统与服务器和工作负载完全不匹配。
- 盒子上的 CPU(处理核心)数量 这实际上也包括正在运行的 SQL Server 版本。在企业版中,CHECKDB 可以在机箱中的所有 CPU 上并行运行(或者在编译 CHECKDB 内部查询时查询处理器决定并行运行的 CPU 数量)。并行运行可以显著提高 CHECKDB 的性能并缩短运行时间,只要数据库也分布在多个文件中(这样 IO 就可以并行化)。有一种巧妙的算法允许 CHECKDB 并行运行,我将在以后的文章中详细解释。另一方面,CHECKDB 可以在企业版中并行运行这一事实在某些情况下可能不利,因此一些 DBA 选择强制 CHECKDB 为单线程。SAP 通常建议这样做以帮助提高用户查询的可预测性。执行此操作的方法是打开记录的跟踪标志 2528。
- 放置 tempdb 的磁盘的速度 针对 VLDB 运行 CHECKDB 会占用大量内存来存储内部状态,而对于 VLDB,内存需求通常超过 SQL Server 可用的内存量。在这种情况下,状态会被缓存到 tempdb,因此 tempdb 的性能可能是 CHECKDB 性能的一个关键因素。请参阅此文章以了解更多详细信息,以及如果 tempdb 太小,CHECKDB 会如何耗尽磁盘空间。
- 数据库模式的复杂性 这会对 CHECKDB 的运行时间产生很大影响,因为它会影响 CHECKDB 所需的 CPU 数量。例如,CHECKDB 执行的最昂贵的检查是针对非聚集索引的。它需要检查非聚集索引中的每一行是否恰好映射到表的堆或聚集索引中的一行,以及每个堆/聚集索引行是否恰好在每个非聚集索引中有一个匹配的行。尽管有一种非常高效的算法可以做到这一点,但它仍然占用了 CHECKDB 使用的总 CPU 的 30% 左右!还有许多其他检查只有在数据库中使用了这些功能时才会执行 - 例如计算列评估、行外 LOB 值之间的链接、服务代理、XML 索引、索引视图 - 因此您可以看到,仅凭经验因素不足以确定运行时间。
- 指定了哪些选项 这几乎与 #7 相同,通过指定各种选项,您可以限制 CHECKDB 实际执行的检查。例如,使用 WITH NOINDEX 选项将关闭我在 #7 中描述的非聚集索引检查,使用 WITH PHYSICAL_ONLY 选项将关闭所有逻辑检查,大大减少 CHECKDB 的运行时间,并使其几乎总是受 IO 限制而不是受 CPU 限制(事实上,这是 VLDB 的 DBA 用来使 CHECKDB 的运行时间易于管理的最常见选项)。需要注意的一件事是 - 如果您指定任何修复选项,CHECKDB 始终以单线程运行,即使在企业版的多进程框上也是如此。
- 数据库中存在的损坏的数量和类型 同样,这与第 7 和第 8 点类似。如果存在任何损坏,可能会触发额外检查以尝试找出损坏的更多细节。例如,对于非聚集索引检查,算法针对不存在损坏的情况进行了非常严格的调整(考虑到 CHECKDB 每天在世界各地运行数百万次,绝大多数情况都是如此)。当检测到非聚集索引损坏时,必须使用更深入的算法来准确找出损坏的位置,这涉及重新扫描一堆数据,因此需要花费更多时间。还有其他一些类似的算法。
现在要记住的另一件事是,使用 REPAIR_ALLOW_DATA_LOSS 会使检查单线程运行,因此修复顺序正确 - 这会使其运行时间更长。查看 2005 SP2+ 上的错误日志中的消息 5268 - 它表示深度挖掘,正如我上面提到的。
概括 所以你可以看出,没有简单的答案。希望这能有所帮助!
PS 忘记说了,在 SQL 2005 中我向 DBCC CHECKDB 添加了进度报告。您可以查询sys.dm_exec_requests
DMV 并查找该percent_complete
列。
答案2
这完全取决于数据库的大小(您说的是 47MB)、损坏量、系统速度等。为了确保万无一失,我会继续让它运行,直到您遇到超时或其他错误。或者,如果您有已知的良好备份,请恢复它。
您还可以启动进程探索器并查看 CPU/磁盘使用情况,看看它是否实际在执行任何操作或“挂断”。
答案3
这个答案显然与保罗对你的具体问题的精彩回答相差甚远。
然而,如果 SharePoint 中的搜索数据库损坏,则重置搜索索引并重新抓取内容的速度可能比尝试修复搜索数据库中的任何损坏要快得多,因为数据库大小为 47MB。步骤如下(知识库文章涉及不同的问题,但重置搜索索引/数据库的步骤相同):http://support.microsoft.com/kb/948909
找出损坏的根本原因,并在内容数据库上对 CheckDB 运行时进行基准测试,仍然不会有什么坏处,但搜索数据库本身就是一个半瞬态实体。你唯一的问题就是完全爬取(你可能希望在非高峰时段运行......这会占用大量的 CPU 和 I/O)。