收缩 tempdb 数据库

适用于: SQL Server Azure SQL 托管实例

本文讨论可用于收缩 SQL Server 中 tempdb 数据库的各种方法。

可以使用下列任一方法来更改 tempdb 大小。 本文介绍了前三个选项。 如果要使用 SQL Server Management Studio (SSMS),请按照收缩数据库中的说明进行操作。

方法 需要重启? 详细信息
ALTER DATABASE 提供对默认 tempdb 文件(tempdevtemplog)大小的完整控制。
DBCC SHRINKDATABASE 在数据库级别运行。
DBCC SHRINKFILE 允许收缩单个文件。
SQL Server Management Studio 通过图形用户界面收缩数据库文件。

注解

默认情况下,tempdb 数据库配置为根据需要自动增长。 因此,此数据库可能会意外地增长到大于所需大小的大小。 较大 tempdb 数据库大小不会对 SQL Server 的性能产生不利影响。

SQL Server 启动时,tempdb 使用数据库的副本重新创建 model,而 tempdb 重置为其上次配置的大小。 配置的大小是使用文件大小更改操作(例如使用 MODIFY FILE 选项的 ALTER DATABASE,或者 DBCC SHRINKFILEDBCC SHRINKDATABASE 语句)设置的最后一个显式大小。 因此,除非必须使用不同的值或立即处理大型 tempdb 数据库,否则可以等待 SQL Server 服务的下一次重启以缩减大小。

tempdb 活动正在进行时,可以收缩 tempdb。 但是,可能会遇到其他错误,例如阻止、死锁等,从而阻碍收缩完成。 因此,为了确保成功收缩 tempdb,我们建议在服务器处于单用户模式或停止所有 tempdb 活动时执行此操作。

SQL Server 只记录 tempdb 事务日志中足够的信息来回滚事务,但在数据库恢复期间不会重做事务。 此功能提高了 INSERTtempdb 语句的性能。 此外,无需记录信息以重做任何事务,因为 tempdb 每次重新启动 SQL Server 时都会重新创建。 因此,它没有要前滚或回滚的事务。

有关管理和监视 tempdb 的详细信息,请参阅容量规划监视 tempdb 使用情况

使用 ALTER DATABASE 命令

注意

此命令仅对默认 tempdb 逻辑文件 tempdevtemplog 执行。 如果更多文件添加到 tempdb 中,则可以在重启 SQL Server 即服务后将其收缩。 所有 tempdb 文件都在启动期间重新创建。 但是,它们为空,可以删除。 如果要删除 tempdb 中其他文件,则使用包含 REMOVE FILE 选项的 ALTER DATABASE 命令。

此方法要求重启 SQL Server。

  1. 停止 SQL Server。

  2. 在命令提示符下,以最低配置模式启动实例。 为此,请按照下列步骤进行操作:

    1. 在命令提示符处,切换到安装 SQL Server 的文件夹(替换以下示例中的 <VersionNumber><InstanceName>):

      cd C:\Program Files\Microsoft SQL Server\MSSQL<VersionNumber>.<InstanceName>\MSSQL\Binn
      
    2. 如果实例是 SQL Server 的命名实例,请运行以下命令(替换以下示例中的 <InstanceName>):

      sqlservr.exe -s <InstanceName> -c -f -mSQLCMD
      
    3. 如果实例是 SQL Server 的默认实例,请运行以下命令:

      sqlservr -c -f -mSQLCMD
      

      注意

      参数 -c-f 会导致 SQL Server 以最小配置模式启动,tempdb 数据文件的大小为 1 MB,日志文件的大小为 0.5 MB。 参数 -mSQLCMD 可防止 sqlcmd 以外的任何其他应用程序接管单用户连接。

  3. 使用 sqlcmd 连接到 SQL Server 实例,然后运行以下 Transact-SQL 命令。 替换 <target_size_in_MB> 为所需的大小:

    ALTER DATABASE tempdb MODIFY FILE
    (NAME = 'tempdev', SIZE = <target_size_in_MB>);
    
    ALTER DATABASE tempdb MODIFY FILE
    (NAME = 'templog', SIZE = <target_size_in_MB>);
    
  4. 停止 SQL Server。 为此,请按命令提示符窗口的 Ctrl+C,重启 SQL Server 即服务,然后验证 tempdb.mdftemplog.ldf 文件的大小。

使用 DBCC SHRINKDATABASE 命令

DBCC SHRINKDATABASE 接收参数 target_percent。 数据库收缩后的数据库文件中所需的剩余可用空间百分比。 如果使用 DBCC SHRINKDATABASE,可能需要重启 SQL Server。

  1. 使用 sp_spaceused 存储过程确定 tempdb 中当前正在使用的空间。 然后,计算要用作 DBCC SHRINKDATABASE 参数的剩余可用空间百分比。 此计算基于所需的数据库大小。

    注意

    在某些情况下,可能需要执行 sp_spaceused @updateusage = true 以重新计算所使用的空间并获取更新的报告。 有关详细信息,请参阅 sp_spaceused

    请考虑以下示例:

    假设 tempdb 有两个文件:主数据文件 (tempdb.mdf) 为 1,024 MB,日志文件 (tempdb.ldf) 为 360 MB。 假设 sp_spaceused 报告主数据文件包含 600 MB 的数据。 此外,假设你想要将主数据文件收缩到 800 MB。 计算收缩后剩余可用空间的所需百分比:800 MB - 600 MB = 200 MB。 现在,将 200 MB 除以 800 MB = 25%,这就是你的 target_percent。 事务日志文件相应地收缩,在数据库收缩后保留 25% 或 200 MB 的可用空间。

  2. 使用 SSMS、Azure Data Studio 或 sqlcmd 连接到 SQL Server,然后运行以下 Transact-SQL 命令。 将 <target_percent> 替换为所需的百分比:

    DBCC SHRINKDATABASE (tempdb, '<target_percent>');
    

tempdb 上的 DBCC SHRINKDATABASE 命令存在限制。 数据和日志文件的目标大小不能小于创建数据库时指定的大小,也不能小于使用文件大小更改操作(例如使用 MODIFY FILE 选项的 ALTER DATABASE)显式设置的最后一个大小。 DBCC SHRINKDATABASE 的另一个限制是参数 target_percentage 的计算及其对所用当前空间的依赖。

使用 DBCC SHRINKFILE 命令

使用 DBCC SHRINKFILE 命令收缩各个 tempdb 文件。 DBCC SHRINKFILE 提供的灵活性比 DBCC SHRINKDATABASE 更高,因为你可以在单个数据库文件上使用,而不会影响属于同一数据库的其他文件。 DBCC SHRINKFILE 接收 target_size 参数。 这是数据库文件所需的最终大小。

  1. 确定主数据文件 (tempdb.mdf)、日志文件 (templog.ldf) 和添加到 tempdb 的其他文件所需的大小。 确保文件中使用的空间小于或等于所需的目标大小。

  2. 使用 SSMS、Azure Data Studio 或 sqlcmd 连接到 SQL Server,然后针对要收缩的特定数据库文件运行以下 Transact-SQL 命令。 替换 <target_size_in_MB> 为所需的大小:

    USE tempdb;
    GO
    
    -- This command shrinks the primary data file
    DBCC SHRINKFILE (tempdev, '<target_size_in_MB>');
    GO
    
    -- This command shrinks the log file, examine the last paragraph.
    DBCC SHRINKFILE (templog, '<target_size_in_MB>');
    GO
    

DBCC SHRINKFILE 的优点是可以将文件大小缩减到小于其原始大小。 可以在任何数据或日志文件发出 DBCC SHRINKFILE。 不能使数据库小于 model 数据库的大小。

运行收缩操作时出现错误 8909

如果 tempdb 正在使用,并且你尝试使用 DBCC SHRINKDATABASEDBCC SHRINKFILE 命令缩小它,则可能会收到类似于以下内容的消息,具体取决于所使用的 SQL Server 版本:

Server: Msg 8909, Level 16, State 1, Line 1 Table error: Object ID 0, index ID -1, partition ID 0, alloc unit ID 0 (type Unknown), page ID (6:8040) contains an incorrect page ID in its page header. The PageId in the page header = (0:0).

此错误并不代表 tempdb 中任何真正的损坏。 但是,可能有其他原因导致类似错误 8909 的物理数据损坏错误,这些原因包括 I/O 子系统问题。 因此,如果错误发生在收缩操作外部,则应进行更多调查。

尽管将 8909 消息返回到应用程序或正在执行收缩操作的用户,但收缩操作不会失败。