2

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

现在我可以深入了解它的细节,但我认为我最好从高层次问:将数据复制到这种规模的最佳方法是什么?最好采用一个小集合(3 个条目)并将其复制到 18,000,000,还是应该采用具有 100,000 条记录的现有数据库并减少复制次数?

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

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

但是对于这种大小,它似乎被锁定(SQL Management Studio 崩溃),运行速度非常慢,或者什么都不做,但仍然像它一样(没有 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,没有第三方工具或它附带的任何东西,我们希望保持这种状态。

任何例子都会很棒,提前谢谢!!!

4

1 回答 1

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

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

于 2012-06-25T21:01:16.623 回答