我有一张200亿行的表格。表没有任何索引,因为它是在飞行中创建的,用于执行批量插入操作。该表正在存储过程中使用,该过程执行以下操作
Delete A
from master a
inner join (Select distinct Col from TableB ) b
on A.Col = B.Col
Insert into master
Select *
from tableB
group by col1,col2,col3
TableB
是有200亿行的那个。我不想直接执行SP,因为完成执行可能需要数天。 Master
也是一个庞大的表格,并且在Col
或者有没有办法快速执行此操作
答案 0 :(得分:2)
我使用了与this one类似的方法。如果可以的话,我建议将数据库置于批量记录恢复模式而不是完全恢复模式。
博客条目转载如下以供将来证明。
以下是用于传输大量记录的技术 一张桌到另一张桌子。由于几个原因,这很好地扩展。 首先,这不会在提交之前填满整个日志 交易。相反,它将以10,000个块填充表格 记录。其次,它通常要快得多。你必须要玩 批量大小。有时它在10,000时效率更高, 有时500,000,具体取决于系统。
如果您不需要插入现有表格,只需要一个 表的副本,最好做一个
SELECT INTO
。但是为此 例如,我们正在插入现有的表格。你应该做的另一个技巧是改变恢复模型 数据库简单。这样,记录的记录就会少得多 交易日志。
下面的
WITH (TABLOCK)
仅适用于SQL 2008。DECLARE @BatchSize INT = 10000 WHILE 1 = 1 BEGIN INSERT INTO [dbo].[Destination] --WITH (TABLOCK) -- Uncomment for 2008 ( FirstName ,LastName ,EmailAddress ,PhoneNumber ) SELECT TOP(@BatchSize) s.FirstName ,s.LastName ,s.EmailAddress ,s.PhoneNumber FROM [dbo].[SOURCE] s WHERE NOT EXISTS ( SELECT 1 FROM dbo.Destination WHERE PersonID = s.PersonID ) IF @@ROWCOUNT < @BatchSize BREAK END
通过上面的例子,重要的是至少要有一个非 两个表中
PersonID
上的聚簇索引。传输记录的另一种方法是使用多个线程。指定 一系列记录如下:
INSERT INTO [dbo].[Destination] ( FirstName ,LastName ,EmailAddress ,PhoneNumber ) SELECT TOP(@BatchSize) s.FirstName ,s.LastName ,s.EmailAddress ,s.PhoneNumber FROM [dbo].[SOURCE] s WHERE PersonID BETWEEN 1 AND 5000 GO INSERT INTO [dbo].[Destination] ( FirstName ,LastName ,EmailAddress ,PhoneNumber ) SELECT TOP(@BatchSize) s.FirstName ,s.LastName ,s.EmailAddress ,s.PhoneNumber FROM [dbo].[SOURCE] s WHERE PersonID BETWEEN 5001 AND 10000
为了获得超快的性能,我建议使用SSIS。 特别是在SQL Server 2008中。我们最近转移了1700万 在同一台服务器上执行SSIS包的5分钟内记录 作为它之间转移的两个数据库。
SQL Server 2008 SQL Server 2008已对其进行了更改 插入记录时的记录机制。以前,要做插入 记录最少,您必须执行
SELECT.. INTO
。 现在,如果可以锁定,则可以执行最少记录的插入 你插入的桌子。以下示例显示了一个示例 这个。此规则的例外情况是,如果您有聚簇索引 表和表不是空的。如果表是空的而你 获取一个表锁,你有一个聚集索引,它将是 记录最少。但是,如果表中有数据,则插入 将被记录。现在,如果堆上有非聚集索引,那么 你获得一个表锁,那么只有非聚集索引 登录。在插入之前删除索引总是更好 记录。要确定日志记录量,您可以使用以下语句
SELECT * FROM ::fn_dblog(NULL, NULL)
上面的信用归功于SQL Server Planet的Derek Dieter。
答案 1 :(得分:1)
如果您在将表格传递到存储过程时设置为you can pass a table-valued parameter to a stored procedure in SQL Server 2008。你可能会对建议的其他一些方法有更好的运气,比如分区。在具有200亿行的表上选择distinct可能是问题的一部分。我想知道一些非常基本的调整是否也不会有所帮助:
Delete A
from master a
where exists (select 1 from TableB b where b.Col = a.Col)