簡體   English   中英

如何在SQL Server中提高游標的性能

[英]How to improve the performance of a Cursor in SQL Server

我有一個表tblLogins ,其中保存了20萬個用戶數據。

我需要在另一個table為每個用戶插入30條記錄。 我將光標用於此任務。 但是我寫的腳本要花很多時間。

它僅在2小時內為6萬個用戶插入了數據。

我已經在google上找到了解決方案,但沒有發現任何可以改善性能的內容。

以下是我編寫的腳本。

DECLARE @LoginID int
DECLARE @DomainID int

DECLARE curDomain CURSOR FAST_FORWARD 
FOR SELECT tbldomains_id FROM  tblDomains

OPEN curDomain 

FETCH NEXT FROM curDomain INTO @DomainID

WHILE @@FETCH_STATUS = 0

BEGIN
 --cur2 starts

 DECLARE curLogin CURSOR FAST_FORWARD 
 FOR SELECT tbllogins_id FROM  tbllogins where tbldomains_id = @DomainID

 OPEN curLogin 

 FETCH NEXT FROM curLogin INTO @LoginID

 WHILE @@FETCH_STATUS = 0

 BEGIN

 --code starts

 if not exists(select 1 from tblWidgetProperties where tblLogin_id = @LoginID)
 begin
 Insert tblWidgetProperties values(1,@LoginID,'isEnabled','True')
 Insert tblWidgetProperties values(2,@LoginID,'isEnabled','True')
 Insert tblWidgetProperties values(3,@LoginID,'isEnabled','True')
 Insert tblWidgetProperties values(4,@LoginID,'isEnabled','True')
 Insert tblWidgetProperties values(5,@LoginID,'isEnabled','True')
 Insert tblWidgetProperties values(6,@LoginID,'isEnabled','True')
 Insert tblWidgetProperties values(7,@LoginID,'isEnabled','True')
 Insert tblWidgetProperties values(8,@LoginID,'isEnabled','True')
 Insert tblWidgetProperties values(9,@LoginID,'isEnabled','True')
 Insert tblWidgetProperties values(10,@LoginID,'isEnabled','True')
 Insert tblWidgetProperties values(11,@LoginID,'isEnabled','True')
 end

 if not exists(select 1 from tblWidgetPosition where tblLogins_id = @LoginID)
 begin
 Insert tblWidgetPosition values(3,1.0,@LoginID)
 Insert tblWidgetPosition values(4,1.01,@LoginID)
 Insert tblWidgetPosition values(5,1.02,@LoginID)
 Insert tblWidgetPosition values(11,1.03,@LoginID)
 Insert tblWidgetPosition values(1,2.00,@LoginID)
 Insert tblWidgetPosition values(7,2.01,@LoginID)
 Insert tblWidgetPosition values(9,2.02,@LoginID)
 Insert tblWidgetPosition values(8,2.03,@LoginID)
 Insert tblWidgetPosition values(6,3.0,@LoginID)
 Insert tblWidgetPosition values(2,3.01,@LoginID)
 Insert tblWidgetPosition values(10,3.02,@LoginID)
 end

 --code ends

 FETCH NEXT FROM curLogin INTO @LoginID

 END

 CLOSE curLogin 

 DEALLOCATE curLogin 

 --cur2 ends

 FETCH NEXT FROM curDomain INTO @DomainID

 END

您應該能夠將它們寫成兩個插入,根本沒有游標

就像是:

;WITH NewData AS (
   SELECT 1 as n UNION ALL
   SELECT 2 as n UNION ALL
   SELECT 3 as n UNION ALL
   SELECT 4 as n UNION ALL
   SELECT 5 as n UNION ALL
   SELECT 6 as n UNION ALL
   SELECT 7 as n UNION ALL
   SELECT 8 as n UNION ALL
   SELECT 9 as n UNION ALL
   SELECT 10 as n UNION ALL
   SELECT 12 as n
)
INSERT INTO tblWidgetProperties (/* Some column list, currently unknown */)
SELECT nd.n,tl.tbllogins_id,'isEnabled','true'
FROM
    NewData nd
       cross join
    tblLogins tl
WHERE
    tl.tbldomains_id in (select tbldomains_id from tblDomains) and
    tl.tbllogins_id not in (select tblLogin_id from tblWidgetProperties)

留給讀者練習以對其他目標表執行基本相同的轉換。 如果數據每行不同,則在NewData CTE中添加更多列。 如果所有行的數據都是固定的,則在選擇中保持內聯值,如上所示。

逐行插入可能非常慢。 將數據准備到CSV文件中,然后使用BULK INSERT進行工作。 請注意數據中可能會破壞插入內容的特殊字符。

BULK INSERT tblWidgetProperties
FROM 'c:\temp\WidgetProperties.tbl'  
WITH  
  (  
     FIELDTERMINATOR =',',  
     ROWTERMINATOR = '\n'
   );  

如果不能選擇“大BULK INSERT ,則應監視正在減慢插入速度的內容。 在插入表的表上禁用觸發器可能會有所幫助。

您正在做很多插入操作。 要減少插入量,請嘗試創建兩個臨時表。 每一組插入一個。 然后您可以做類似的事情。

if not exists(select 1 from tblWidgetProperties where tblLogin_id = @LoginID)
 begin
    insert into tblWidgetProperties 
    Select [1],@LoginID,[2],[3]) from #tmpWidgetProperties
 end

if not exists(select 1 from tblWidgetPosition where tblLogins_id = @LoginID)
 begin
    Insert tblWidgetPosition 
    select [1], [2], @LoginID from #tmpWidgetPositions
 end

但在此之前,我將先看一下CTE和MERGE。

干杯馬丁

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM