Sql 使用游标从现有数据集生成虚拟数据很慢

Sql 使用游标从现有数据集生成虚拟数据很慢,sql,sql-server,performance,sql-server-2016,Sql,Sql Server,Performance,Sql Server 2016,我试图从表中现有的数据生成虚拟数据。我只想将表1中的记录数增加到N个指定的数量。其他表应根据外键引用增加 这些表具有一对多关系。对于表1中的一条记录,我可以在表2中有多个条目,在表3中,我可以根据第二个表的ID有多条记录 由于ID是主键,我要么通过 SET @NEWLY_INSERTED_ID = SCOPE_IDENTITY() 插入到表1并在表2的insert中使用后,或将它们插入到temp表并将它们连接起来,以获得与表3相同的结果 这是我使用光标的方法 以上代码有效!它生成我需要的数据。

我试图从表中现有的数据生成虚拟数据。我只想将表1中的记录数增加到N个指定的数量。其他表应根据外键引用增加

这些表具有一对多关系。对于表1中的一条记录,我可以在表2中有多个条目,在表3中,我可以根据第二个表的ID有多条记录

由于ID是主键,我要么通过

SET @NEWLY_INSERTED_ID = SCOPE_IDENTITY()
插入到表1并在表2的insert中使用后,或将它们插入到temp表并将它们连接起来,以获得与表3相同的结果

这是我使用光标的方法

以上代码有效!它生成我需要的数据。但是,它非常非常慢。只是做一些比较。表1的数据初始加载量约为60000条记录,表2为74000条记录,表3为3400条记录

我试图在表1中插入9000行。使用上述代码,需要17:05:01秒才能完成


关于如何优化查询以加快运行速度,有什么建议吗?我的目标是在表1中插入1-2百万条记录,而不必等待几天。我不受光标的束缚。我可以以任何其他可能的方式实现相同的结果。

您只能使用while循环进行插入,不需要使用游标。您可以演示一个示例吗?
DECLARE @MyId as INT;
DECLARE @myCursor as CURSOR;

DECLARE @DESIRED_ROW_COUNT INT = 70000
DECLARE @ROWS_INSERTED INT = 0
DECLARE @CURRENT_ROW_COUNT INT = 0
DECLARE @NEWLY_INSERTED_ID INT
DECLARE @LANGUAGE_PAIR_IDS TABLE ( LangugePairId INT, NewId INT, SourceLanguage varchar(100), TargetLangauge varchar(100) )

WHILE (@ROWS_INSERTED < @DESIRED_ROW_COUNT)
BEGIN

SET @myCursor = CURSOR FOR
SELECT Id FROM MyTable
SET @CURRENT_ROW_COUNT = (SELECT COUNT(ID) FROM MyTable)

OPEN @myCursor;
    FETCH NEXT FROM @myCursor INTO @MyId;
    WHILE @@FETCH_STATUS = 0
        BEGIN

            IF ((@CURRENT_SUBMISSION_COUNT < @DESIRED_ROW_COUNT) AND (@ROWS_INSERTED < @DESIRED_ROW_COUNT))
            BEGIN

                INSERT INTO [dbo].[MyTable]
                           ([Column1]
                           ([Column2]
                           ([Column3]
                           )

                     SELECT 
                      ,convert(numeric(9,0),rand() * 899999999) + 100000000
                      ,COlumn2
                      ,Colum3
                    FROM MyTable
                    WHERE Id = @MyId

                    SET @NEWLY_INSERTED_ID = SCOPE_IDENTITY()

                    INSERT INTO [dbo].[Language]
                               ([MyTable1Id]
                               ,[Target]
                               ,[Source]
                    OUTPUT inserted.Id, inserted.MyTable1Id, inserted.Source, inserted.[Target] INTO @LANGUAGE_PAIR_IDS (LangugePairId, NewId, SourceLanguage, TargetLangauge)
                    SELECT 
                          @NEWLY_INSERTED_ID
                          ,[Target]
                          ,[Source]
                     FROM [dbo].[Language] 
                     WHERE MyTableId = @MyId
                     ORDER BY Id

                     DECLARE @tbl AS TABLE (newLanguageId INT, oldLanguageId INT, sourceLanguage VARCHAR(100), targetLanguage VARCHAR(100))

                     INSERT INTO @tbl (newLanguageId, oldLanguageId, sourceLanguage, targetLanguage)
                     SELECT 0, id, [Source], [Target] MyTable1Id FROM Language WHERE MyTable1Id = @MyId ORDER BY Id

                     UPDATE t
                     SET t.newlanguageid = lp.LangugePairId
                     FROM @tbl t
                     JOIN @LANGUAGE_PAIR_IDS lp
                     ON t.sourceLanguage = lp.SourceLanguage
                     AND t.targetLanguage = lp.TargetLangauge

                     INSERT INTO [dbo].[Manager]
                              ([LanguagePairId]
                              ,[UserId]
                              ,[MyDate])
                     SELECT 
                             tbl.newLanguageId 
                           ,p.[UserId]
                           ,p.[MyDate]
                     FROM Manager m
                     INNER JOIN @tbl tbl
                     ON m.LanguagePairId = tbl.oldLanguageId
                     WHERE m.LanguagePairId in (SELECT Id FROM Language WHERE MyTable1Id = @MyId) -- returns the old language pair id

                     SET @ROWS_INSERTED += 1
                     SET @CURRENT_ROW_COUNT +=1
            END
            ELSE
            BEGIN
                PRINT 'REACHED EXIT'
                SET @ROWS_INSERTED = @DESIRED_ROW_COUNT
                BREAK
            END
    FETCH NEXT FROM @myCursor INTO @MyId;
END
CLOSE @myCursor
DEALLOCATE @myCursor
END