我有一个表tblLogins
,其中保存了200万个用户数据。
我需要为另一个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 :(得分: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中,如上所示。
答案 1 :(得分:0)
逐行插入可能会非常慢。准备数据到CSV文件并使用BULK INSERT
完成工作。请注意数据中可能破坏插入内容的特殊字符。
BULK INSERT tblWidgetProperties
FROM 'c:\temp\WidgetProperties.tbl'
WITH
(
FIELDTERMINATOR =',',
ROWTERMINATOR = '\n'
);
如果BULK INSERT
不是一个选项,那么你应该监控什么是减慢插入速度。您插入的表格上的Disabling triggers可能会有所帮助。
答案 2 :(得分: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。
干杯马丁