sql server free tempdb

时间:2014-11-07 10:32:18

标签: sql-server tsql sql-server-2008-r2 tempdb

我们在SQL Server 2008R2-SP1中运行导入存储过程,一次将数千行加载到多个表中。我们遇到tempDBtransaction log尺寸问题。

这样的事情:

CREATE PROCEDURE spReallyHugeImportDataProcedure
    @id int
AS
BEGIN
    CREATE TABLE #temp(...)

    INSERT INTO #temp
    SELECT *
    FROM AlotOfJoins

    INSERT INTO FinalTable
    SELECT * FROM AlotOfJoins

    DROP #tempTable

    INSERT INTO #temp
    SELECT *
    FROM AlotOfJoins

    INSERT INTO FinalTable
    SELECT * FROM AlotOfJoins

    DROP #tempTable

    INSERT INTO #temp
    SELECT *
    FROM AlotOfJoins

    INSERT INTO FinalTable
    SELECT * FROM AlotOfJoins

    DROP #tempTable

    -- And so on....

END

我们正在尝试拆分整个过程,并为一小组数据运行几次。

像这样:

CREATE PROCEDURE spReallyHugeImportDataProcedure
   @id int
AS
BEGIN

    DECLARE @SomeSortOfCounter int = 100
    WHILE(@SomeSortOfCounter <> 0)
    BEGIN
        -- TRY TO START A NEW TRANSACTION
        BEGIN TRAN

        CREATE TABLE #temp(...)

        INSERT INTO #temp
        SELECT *
        FROM AlotOfJoins
        WHERE SomeFileterWorkinWithTheCounter = @SomeSortOfCounter

        INSERT INTO FinalTable
        SELECT * FROM AlotOfJoins

        DROP #tempTable

        INSERT INTO #temp
        SELECT *
        FROM AlotOfJoins
        WHERE SomeFileterWorkinWithTheCounter = @SomeSortOfCounter

        INSERT INTO FinalTable
        SELECT * FROM AlotOfJoins

        DROP #tempTable

        INSERT INTO #temp
        SELECT *
        FROM AlotOfJoins
        WHERE SomeFileterWorkinWithTheCounter = @SomeSortOfCounter

        INSERT INTO FinalTable
        SELECT * FROM AlotOfJoins

        DROP #tempTable

        -- And so on....

        -- TRY TO RELASE TEMP OBJECTS, 
        -- OR GIVE TO THE SERVER THE OPORTUNITY TO DO IT
        COMMIT

        SET @SomeSortOfCounter = @SomeSortOfCounter - 1
    END
END

SQL Server引擎是否可以在这些内部事务之间工作?

2 个答案:

答案 0 :(得分:1)

选项1:使用用户数据库中的表

如果确实需要将数据存储在临时表中,请在用户数据库(例如ImportTemp或目标数据库)中构建该表,然后使用它而不是tempdb。在这种情况下,SQL Server不应在TempDB中使用尽可能多的空间,并且您的数据将被持久存储 - &gt;您可以重复使用它,并且可以将加载程序查询分成多个批次。

您可以选择将此表移动到其他文件组,以防止写入大写,并降低干扰其他进程的可能性。

在这种情况下,步骤是:

  1. 删除'temp'(如果存在)
  2. 创建'temp'(在用户数据库中)
  3. 在'temp'表中填入必要的数据
  4. 从持久化的'temp'表
  5. 加载目标表
  6. 删除'temp'表以释放数据文件中的空间
  7. (可选)收缩与“temp”表相关的数据和日志文件
  8. 如果您经常使用此导入表,则只能在使用前后截断它而不是删除并重新创建它。

    选项2:使用ETL工具

    使用ETL工具可以处理批次/缓冲区中的数据。如果您使用的是SQL Server Standard或更高版本,则可以选择使用SSIS (SQL Server Integration Services)

    DBCC SHRINKFILE

    您可以使用DBCC SHRINKFILE命令从数据和日志文件中释放未使用的空间:

    USE [YourDatabase]
    
    DBCC SHRINKFILE 
    (
        { file_name | file_id } 
        { [ , EMPTYFILE ] 
        | [ [ , target_size ] [ , { NOTRUNCATE | TRUNCATEONLY } ] ]
        }
    )
    [ WITH NO_INFOMSGS ]
    

    实施例

    USE [tempdb]
    DBCC SHRINKFILE (tempdb_data, TRUNCATEONLY)
    

    <强>任选地

    您可以通过向TempDB添加其他数据文件来传播驱动器上的TempDB文件:

    ALTER DATABASE tempdb
        ADD FILE (NAME = tempdev2, FILENAME = 'W:\tempdb2.mdf', SIZE = 256);
    

    相关问题:How to spread tempdb over multiple files?

答案 1 :(得分:0)

简单的答案是肯定的,只要存储过程之外没有外部事务。此外,没有理由添加显式交易。简单地创建一个循环,只使用每个语句的一大块记录将让你的tlog空间被重用,你不会一次强制所有记录进入临时表。