我得到一个6M行表需要每天发送到另一台服务器。 当我通过测试时似乎永远不会完成:
insert into serverA.dbName.dbo.table1
select * from serverB.dbName.dbo.table1
有"每次做10000行"
类似
insert into serverA.dbName.dbo.table1
select * from serverB.dbName.dbo.table1
**by numOfRowEachTime=10000**
否则我会写一个循环。
答案 0 :(得分:0)
单个事务中的600万行是一个相当大的块,并且链接服务器上的DML语句也不是很好。但是要考虑的两种方法(对我有用)是:
如果有一种简单的方法可以按顺序复制它们(例如ID字段),那么您可以:
在ServerB上写一个proc,它执行类似于以下的循环:
DECLARE @StartingID INT = 1,
@EndingID INT,
@DataToTransport NVARCHAR(MAX);
SELECT @StartingID = StartingID FROM dbo.ProcessStatus;
WHILE (1 = 1)
BEGIN
;WITH cte AS
(
SELECT TOP (10000) t1.ID,
ROW_NUMBER() OVER (ORDER BY t1.ID ASC) AS [RowNum]
FROM dbo.Table1 t1
WHERE t1.ID >= @StartingID
)
SELECT TOP (1) @EndingID = cte.[ID] FROM cte
ORDER BY cte.[RowNum] DESC;
IF (@@ROWCOUNT = 0)
BEGIN
UPDATE dbo.ProcessStatus SET StartingID = 1;
BREAK; -- reset to start at the beginning and exit
END;
SET @DataToTransport = (CONVERT(NVARCHAR(MAX), (
SELECT t1.* FROM dbo.Table1 t1
WHERE t1.ID BETWEEN @StartingID AND @EndingID
FOR XML RAW));
EXEC [ServerA].[dbName].[dbo].Table1_ImportFromServerB @DataToTransport;
UPDATE dbo.ProcessStatus SET StartingID = @StartingID;
SET @StartingID = (@EndingID + 1);
END;
INSERT INTO Table1 SELECT ... FROM (either @XMLvariable.Nodes or OPENXML)
[ProcessStatus]
表只是为了跟踪当前位置,以防过程失败,因此它可以从停止的位置开始,或者您甚至可以设置X迭代的时间限制或计数器并安排到每隔N分钟左右从一个SQL代理作业运行(这就是我一直这样做的原因)。
使用SQLCLR来使用为此类任务设计的SqlBulkCopy
类。它本质上与BCP,OPENROWSET(BULK ...)和BULK INSERT使用的API相同。您可以编写自己的基于CLR的存储过程,或者已经在SQL#库(我是其作者,但同样免费)中已经完成并且可以免费获得。存储过程称为DB_BulkCopy
,允许设置批量大小。