我们在SQL Server 2008R2-SP1中运行导入存储过程,一次将数千行加载到多个表中。我们遇到tempDB
和transaction 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引擎是否可以在这些内部事务之间工作?
答案 0 :(得分:1)
选项1:使用用户数据库中的表
如果确实需要将数据存储在临时表中,请在用户数据库(例如ImportTemp或目标数据库)中构建该表,然后使用它而不是tempdb。在这种情况下,SQL Server不应在TempDB中使用尽可能多的空间,并且您的数据将被持久存储 - &gt;您可以重复使用它,并且可以将加载程序查询分成多个批次。
您可以选择将此表移动到其他文件组,以防止写入大写,并降低干扰其他进程的可能性。
在这种情况下,步骤是:
如果您经常使用此导入表,则只能在使用前后截断它而不是删除并重新创建它。
选项2:使用ETL工具
使用ETL工具可以处理批次/缓冲区中的数据。如果您使用的是SQL Server Standard或更高版本,则可以选择使用SSIS (SQL Server Integration Services)。
您可以使用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);
答案 1 :(得分:0)
简单的答案是肯定的,只要存储过程之外没有外部事务。此外,没有理由添加显式交易。简单地创建一个循环,只使用每个语句的一大块记录将让你的tlog空间被重用,你不会一次强制所有记录进入临时表。