2017-08-29 32 views
-1

我有一個表tblLogins,其中有200k個用戶數據保存在其中。如何提高SQL Server中光標的性能

我需要爲另一個table中的每個用戶插入30條記錄。我使用光標執行此任務。但是我寫的腳本花了很多時間。

僅在2小時內爲6萬用戶插入數據。

我已經看過谷歌的解決方案,但沒有找到任何有關提高性能。

下面是我寫的腳本。

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 
+0

正在從文件中讀取一個選項嗎?然後使用批量插入 –

+0

@RadimBača我沒有任何文件的數據。 –

+0

無法將數據序列化到服務器上的文件中? –

回答

4

你應該能夠在寫這些是隻有兩個刀片,沒有遊標所有

喜歡的東西:

;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中添加更多列。如果數據對於所有行都是固定的,請將值保持在select中,如上所示。

+0

謝謝。它效果很好。僅需2分鐘即可插入約37條記錄。 –

+0

@CodeRider請不要在這裏使用印度語,其他地方的人不會理解他們。 –

+0

@JamesZ - 我用來糾正用法。但我開始轉向。我已經看到了lacs或lakhs頻繁使用,我知道是什麼意思。我不確定爲什麼覺得它足夠重要,可以成爲印度的一個指定單位,但如果它很快就會進入英語,我不會感到驚訝。 –

0

按行插入可能會非常緩慢。準備數據到CSV文件並使用BULK INSERT來完成這項工作。請注意數據中可能破壞插入的特殊字符。

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

如果BULK INSERT是不是一種選擇,那麼你應該監控什麼拖慢您的插件。您插入的桌子上的Disabling triggers可能會有所幫助。

+0

那麼,我需要手動創建這個CSV文件嗎? –

+0

你用C#和C++編程,所以他們中的任何一個都準備好了CSV文件。我不知道你如何獲得數據。如果手動完成它是合適的,那就去做吧。 –

0

你正在做很多插入。 要降低插入量,請嘗試創建兩個臨時表。每組插入一個。然後你可以做類似的事情。

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。

乾杯馬丁