[英]Passing a table to a stored procedure
我有一個有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
上具有聚集索引
還是有什么方法可以快速執行此操作
我使用了與此方法類似的方法。 如果可以的話,建議您將數據庫置於批量記錄恢復模式,而不是完全恢復模式。
下面復制了博客條目,以供將來證明。
下面是一種用於將大量記錄從一個表轉移到另一個表的技術。 由於幾個原因,這可以很好地擴展。 首先,這不會在提交事務之前填滿整個日志。 相反,它將以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中。我們最近在5分鍾內傳輸了1700萬條記錄,並且在同一台服務器上執行的SSIS包與在其之間傳輸的兩個數據庫一起執行。
SQL Server 2008 SQL Server 2008在插入記錄時對其日志記錄機制進行了更改。 以前,要進行最少記錄的插入,必須執行
SELECT.. INTO
。 現在,如果您可以鎖定要插入的表,則可以執行最少記錄的插入。 下面的示例顯示了一個示例。 此規則的例外情況是,如果表上有聚集索引並且表不為空。 如果表為空,並且您獲得了表鎖,並且具有聚集索引,那么它將被最小化記錄。 但是,如果表中有數據,則將記錄插入。 現在,如果堆上具有非聚集索引並且獲得了表鎖,則將僅記錄非聚集索引。 最好在插入記錄之前刪除索引。要確定日志記錄的數量,可以使用以下語句
SELECT * FROM ::fn_dblog(NULL, NULL)
以上內容歸功於SQL Server Planet的Derek Dieter。
如果在將表傳遞到存儲過程時一無所獲,則可以在SQL Server 2008中將表值參數傳遞給存儲過程 。 建議使用其他一些方法(例如分區)可能會更好。 在具有200億行的表上選擇“不重復”可能是問題的一部分。 我想知道一些非常基本的調整是否也無濟於事:
Delete A
from master a
where exists (select 1 from TableB b where b.Col = a.Col)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.