为缩放测试复制SQL入口百万次

时间:2012-06-23 03:23:08

标签: sql

对于我们的一个更重要的项目,我们需要通过一些具有超大型数据库的测试集来运行我们的应用程序。我们的正常最大平均值约为100,000个条目,但我们希望测试大约18-24,000,000个条目。

现在我可以详细介绍它,但我认为从高层开始问我更好:将数据复制到那个规模的最佳方法是什么?采取一小组(3个条目)并将其复制到18,000,000是否更好,或者我应该将现有数据库与100,000个记录重复并重复更少次数?

确实需要进行一些数据编辑,因为每个条目需要在一列中具有唯一的GUID,在另一列中具有友好的名称。

我有一个存储过程,我从前同事的存档中清理过,它会记录并在两个唯一列的末尾添加一个实时编号,然后关闭并再次运行。它需要4个小时才能达到6,000,000,我认为这大约是14GB。我们只用过多达100,000条记录,但它确实做得很好。

但是这个大小看起来似乎已经锁定(SQL Management Studio Crashes),真的很慢或只是做什么,但仍然像它一样(没有CPU活动)。并且日志文件变得庞大,如14GB数据库文件的20GB。

这是现在的存储过程:

USE [DBNAME]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE PROCEDURE [dbo].[PERSON_Insert]
@LoopCount int,
@PersonId varchar(50)
AS 
BEGIN
DECLARE @intFlag INT ,@P_FIELD1 Varchar(50),@T_FIELD2 Varchar(10),@T_FIELD3 numeric(11,0), @T_FIELD4 numeric(11,0), @T_FIELD5 varchar(8000), @T_FIELD6 numeric(20,0)
,@TR_FIELD7 Varchar(10),@TR_FIELD8 numeric(11,0), @TR_FIELD9 numeric(11,0), @TR_FIELD10 varchar(8000), @TR_FIELD11 numeric(20,0)
    SET @intFlag = 1
select @P_FIELD1=dbo.MyRegistratonNo(@PersonId)
select @T_FIELD2=dbo.MyENGINETYPE(@PersonId,1)
select @T_FIELD3=dbo.MyTEMPLATEID(@PersonId,1)
select @T_FIELD4=dbo.MyTEMPLATETYPE(@PersonId,1)
select @T_FIELD5=dbo.MyTEMPLATEFEATURE(@PersonId,1)
select @T_FIELD6=dbo.MyTEMPLATESIZE(@PersonId,1)
select @TR_FIELD7=dbo.MyENGINETYPE(@PersonId,2)
select @TR_FIELD8=dbo.MyTEMPLATEID(@PersonId,2)
select @TR_FIELD9=dbo.MyTEMPLATETYPE(@PersonId,2)
select @TR_FIELD10=dbo.MyTEMPLATEFEATURE(@PersonId,2)
select @TR_FIELD11=dbo.MyTEMPLATESIZE(@PersonId,2)
WHILE (@intFlag <=@LoopCount)
BEGIN
INSERT INTO [PERSON]
([PERSONID],[REGISTRATIONNO] , [TYPEID] , [REGISTEREDDATE] , [STATUS])
VALUES(@PersonId+CAST(@intFlag AS varchar(50)),@P_FIELD1+CAST(@intFlag AS varchar(50)),1,GETDATE(),1)
INSERT INTO [TEMPLATES]
([PERSONID],[ENGINETYPE] , [TEMPLATEID] , [TEMPLATETYPE] , [TEMPLATEFEATURE] , [TEMPLATESIZE])
VALUES(@PersonId+CAST(@intFlag AS varchar(50)),@T_FIELD2,@T_FIELD3,@T_FIELD4,@T_FIELD5,@T_FIELD6)
INSERT INTO [TEMPLATES]
([PERSONID],[ENGINETYPE] , [TEMPLATEID] , [TEMPLATETYPE] , [TEMPLATEFEATURE] , [TEMPLATESIZE])
VALUES(@PersonId+CAST(@intFlag AS varchar(50)),@TR_FIELD7,@TR_FIELD8,@TR_FIELD9,@TR_FIELD10,@TR_FIELD11)
PRINT @P_FIELD1 +CAST(@intFlag AS varchar(50))
SET @intFlag = @intFlag + 1
END
END

还有一些标量函数,其中六个使用,并且都遵循相同的格式:

USE [DBNAME]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE FUNCTION [dbo].[MyENGINETYPE]
(@PersonID varchar(50),@TemplateID numeric(11,0))
RETURNS varchar(10)
AS
BEGIN
DECLARE @Return varchar(10)
SELECT @Return = (SELECT ENGINETYPE FROM TEMPLATES WHERE PERSONID=@PersonID AND TEMPLATEID=@TemplateID)
RETURN @Return
END

请记住,我是一个轻量级的脚本编写者/ webdev,不是真正的dba或擅长这样的企业级数据。这就是说这至少是一个体面的方式,或者我用笨重的东西谋杀这台服务器?我们只有SQL Server 2012,没有第三方工具或者它附带的任何东西,我们希望保持这种方式。

任何例子都会令人惊讶,而不是提前!!!

1 个答案:

答案 0 :(得分:0)

这可能会给你一些想法。

SET NOCOUNT ON对于停止“插入1行”消息非常重要。

也许值得考虑在插入之前禁用/删除索引 - 可能会加快速度。

CREATE TABLE Person
(
    PersonId UNIQUEIDENTIFIER DEFAULT NEWID() PRIMARY KEY,
    Blah1 VARCHAR(50) DEFAULT REPLICATE('X', 50)
)
GO

SET NOCOUNT ON
GO

DECLARE @i INT
SET @i = 1

WHILE (@i <= 1000000)
BEGIN
   INSERT INTO Person DEFAULT VALUES 
   SET @i = @i + 1
END

另一种选择是创建一个平面文件,并使用批量插入。创建平面文件可能需要一些努力但应该是一次性的 - 除非您需要更改数据。