Reputation: 2063
I have a table tblLogins
which has 200k users data saved in it.
I need to insert 30 records for each user in an another table
. I used the cursor for this task. But the script I have written takes a lot of time.
It has inserted data only for 60 thousand users in 2 hours.
I have looked over google for the solution but didn't find anything related to improve the performance.
Below is the script I have written.
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
Upvotes: 0
Views: 6990
Reputation: 239646
You should be able to write these as just two inserts, no cursors at all
Something like:
;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)
Exercise left for the reader to perform essentially the same transformation for the other target table. If the data varies per-row then add more columns in the NewData
CTE. If the data is fixed for all rows, keep the values inline in the select, as shown above.
Upvotes: 4
Reputation: 126
You are doing an awful lot of inserts. To lower the amount of inserts, try creating two temporary tables. One for each set of inserts. Then you could do something like.
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
But before doing this I would take a look at CTE and MERGE.
Cheers Martin
Upvotes: 0
Reputation: 10701
Inserting row by row can be very slow. Prepare the data into a CSV file and use BULK INSERT
to do the job. Be aware of the special characters in the data that may spoil the inserts.
BULK INSERT tblWidgetProperties
FROM 'c:\temp\WidgetProperties.tbl'
WITH
(
FIELDTERMINATOR =',',
ROWTERMINATOR = '\n'
);
If BULK INSERT
is not an option then you should monitor what is slowing down your inserts. Disabling triggers on tables where you insert may help.
Upvotes: 0