Sql-Server

插入 25k 行時出現“執行緒被中止”錯誤

  • November 22, 2012

我需要大約每週一次將大約 25k 行的數據儲存到一個表中。為此,我創建了一個對象(通過解析 XML 創建),並將該對像中的數據發送到儲存過程。有一個對象包含表中每一行的數據。

這是儲存過程:

ALTER PROCEDURE [dbo].[BankImport] 
   -- Add the parameters for the stored procedure here
   @bankName nvarchar(50) = null,
   @shortBankName nvarchar(50) = null,
   @branchName nvarchar(50) = null,
   @sortCode int,
   @addresseeName nchar(60) = null,
   @postalName nchar(60) = null,
   @addressLine1 nchar(100) = null,
   @addressLine2 nchar(80) = null,
   @cityOrTown nchar(50) = null,
   @areaOrCounty nchar(60) = null,
   @postCode nchar(12) = null,
   @fasterPayments nchar(10) = null,
   @directDebits nchar(10) = null,
   @chaps nchar(10) = null,
   @chequeCreditClearing nchar(10) = null

AS
BEGIN
   -- SET NOCOUNT ON added to prevent extra result sets from
   -- interfering with SELECT statements.
   SET NOCOUNT ON;

   IF EXISTS (SELECT 1 FROM [dbo].[banks] WHERE sortCode = @sortCode)

       UPDATE [dbo].[banks] 
       SET @bankName = bankName,
           @shortBankName = shortBankName,
           @branchName = branchName,
           @sortCode = sortCode,
           @addresseeName = addresseeName,
           @postalName = postalName,
           @addressLine1 = addressLine1,
           @addressLine2 = addressLine2,
           @cityOrTown = cityOrTown,
           @areaOrCounty = areaOrCounty,
           @postCode = postCode,
           @fasterPayments = fasterPayments,
           @directDebits = directDebits,
           @chaps = chaps,
           @chequeCreditClearing = chequeCreditClearing
       WHERE sortCode = @sortCode

   ELSE

       INSERT INTO [dbo].[banks] VALUES (
           @bankName,
           @shortBankName,
           @branchName,
           @sortCode,
           @addresseeName,
           @postalName,
           @addressLine1,
           @addressLine2,
           @cityOrTown,
           @areaOrCounty,
           @postCode,
           @fasterPayments,
           @directDebits,
           @chaps,
           @chequeCreditClearing
       )

END

它適用於較小的數據集,但全尺寸包含英國每家銀行的每個分行。在給出此錯誤之前,它設法通過大約 15k 行:

Thread was being aborted.

這可能更像是一個超時問題,還是效率低下,還是我還缺少其他東西?

強烈建議您查看表值參數並將您的插入/更新視為一個集合(可能使用MERGE),而不是呼叫單例儲存過程 25,000 次。您可以在此處跳過很多步驟(例如,在 C# 中,您可以將 25K 行填充到 DataTable 中,以便在一次呼叫中輕鬆傳遞給儲存過程),並顯著減少成本。

如果您為銀行行創建類型:

CREATE TYPE dbo.BankRow AS TABLE
(
 SortCode int PRIMARY KEY,
 BankName nvarchar(50),
 ShortBankName nvarchar(50),
 BranchName nvarchar(50),
 AddresseeName nchar(60),
 PostalName nchar(60),
 AddressLine1 nchar(100),
 AddressLine2 nchar(80),
 CityOrTown nchar(50),
 AreaOrCounty nchar(60),
 PostCode nchar(12),
 FasterPayments nchar(10),
 DirectDebits nchar(10),
 Chaps nchar(10),
 ChequeCreditClearing nchar(10)
);

您的程序可能如下所示:

ALTER PROCEDURE dbo.BankImport
 @BankRow dbo.BankRow READONLY
AS
BEGIN
 SET NOCOUNT ON;

 MERGE dbo.Banks AS b
   USING @BankRow AS tvp
   ON tvp.SortCode = b.SortCode
 WHEN MATCHED THEN 
   UPDATE SET BankName = tvp.BankName,
              ShortBankName = tvp.ShortBankName,
              ...         
 WHEN NOT MATCHED THEN
   INSERT (SortCode, BankName, ShortBankName, ...)
   VALUES (tvp.SortCode, tvp.BankName, tvp.ShortBankName, ...)
END
GO

因此,現在您可以將 DataTable 傳遞給儲存過程*一次,*而不是呼叫單例儲存過程 25,000 次。您必須在我放置的位置添加其他列,...並且您還必須調整 C# 程式碼以使用 TVP。

我在這裡寫了一篇關於 TVP 的快速文章,包括一個關於 C# 語法的快速範例:

http://www.sqlperformance.com/2012/08/t-sql-queries/splitting-strings-now-with-less-t-sql

Erland 的文章也很有用:

http://sommarskog.se/arrays-in-sql-2008.html

引用自:https://dba.stackexchange.com/questions/29110