2013-08-28 1 views
1

일부 데이터를 SQL 데이터베이스로 생성하는 쿼리를 만들었지 만 1GB 데이터 생성에는 약 45 분이 걸립니다. 어떻게 데이터 생성의 성능을 향상시킬 수 있습니까?빠른 데이터 생성에 대한 SQL 쿼리

DECLARE @RowCount INT 
DECLARE @RowString VARCHAR(10) 
DECLARE @Random INT 
DECLARE @Upper INT 
DECLARE @Lower INT 
DECLARE @InsertDate DATETIME 

SET @Lower = -730 
SET @Upper = -1 
SET @RowCount = 0 

WHILE @RowCount < 3000000 
BEGIN 
SET @RowString = CAST(@RowCount AS VARCHAR(10)) 
SELECT @Random = ROUND(((@Upper - @Lower -1) * RAND() + @Lower), 0) 
SET @InsertDate = DATEADD(dd, @Random, GETDATE()) 

INSERT INTO Table_1 
    (q 
    ,w 
    ,e 
    ,r 
    ,t 
    ,y) 
VALUES 
    (REPLICATE('0', 10 - DATALENGTH(@RowString)) + @RowString 
    , @InsertDate 
    ,DATEADD(dd, 1, @InsertDate) 
    ,DATEADD(dd, 2, @InsertDate) 
    ,DATEADD(dd, 3, @InsertDate) 
    ,DATEADD(dd, 4, @InsertDate)) 

SET @RowCount = @RowCount + 1 
END 
+0

가능한 중복 ([? 왜 SQL 서버가 느린 삽입입니다] http://stackoverflow.com/questions/1743496/why-are-sql-server-inserts-so-slow) –

+0

당신이 그것을하는 방법에 상관없이 데이터의 공연은 생성하는 데 오랜 시간이 걸릴 것입니다. –

답변

2

당신은 시도 할 수는 다음 :

;with seq as (
    select top (3000000) N = row_number() over (order by @@spid) - 1 from sys.all_columns c1, sys.all_columns c2 
) 
INSERT INTO Table_1 (q, w, e, r, t, y) 
select 
    right('0000000000' + cast(N as varchar(10)), 10) 
    ,p.InsertDate 
    ,DATEADD(dd, 1, p.InsertDate) 
    ,DATEADD(dd, 2, p.InsertDate) 
    ,DATEADD(dd, 3, p.InsertDate) 
    ,DATEADD(dd, 4, p.InsertDate) 
from seq 
    cross apply (select DATEADD(dd, ROUND(((@Upper - @Lower -1) * RAND(checksum(newid())) + @Lower), 0), GETDATE())) p(InsertDate) 
+0

니스, 내보다 훨씬 간결 :) –

+0

완벽하게 작동합니다. 고마워. –

2

문제는 한 번에 한 행씩 데이터를 생성하여 삽입하는 것입니다. SQL Server는 그런 식으로 작동하도록 설계되지 않았습니다. 세트 기반 솔루션을 찾아야합니다. 이 30 초에서 나를 위해에서 근무 :

CREATE TABLE #Table_1 (
    Id INT IDENTITY(1,1) 
    , RowString AS REPLICATE('0', 10 - LEN(CAST(Id AS VARCHAR))) + CAST(Id AS VARCHAR) 
    , Date1 DATETIME 
); 

DECLARE @Upper INT = -1; 
DECLARE @Lower INT = -730; 

INSERT #Table_1 (Date1) 
SELECT TOP 3000000 DATEADD(dd, ROUND(((@Upper - @Lower -1) * RAND(checksum(newid())) + @Lower), 0), GETDATE()) 
FROM ( SELECT number 
      FROM master..spt_values  
      WHERE TYPE = 'P' AND number <= 2000 
     ) a (Number) 
     ,( SELECT number  
      FROM master..spt_values  
      WHERE TYPE = 'P' AND number <= 2000 
     ) b (Number); 

당신은 # 된 table_1의 임시 테이블 위의 데이터가되면이 된 table_1에 삽입하는 간단한 문제이다 :

INSERT Table_1 (q,w,e,r,t,y) 
SELECT RowString, Date1, Date1 + 1, Date1 + 2, Date1 + 3, Date1 + 4 
FROM #Table_1; 
+1

+1,'rand()'대신'rand (checksum (newid()))'를 사용하는 것이 더 좋지만 생성 된 모든 행에서 날짜가 동일하지는 않습니다. –

+0

감사합니다. 내 대답 업데이트 :) –

0

SQL에서 가장 큰 병목 현상은 각 삽입 문이 트랜잭션 로그에 로그를 생성하기 때문에 로깅과 관련이 있습니다. 테이블 변수는 일반적으로 데이터의 매체 볼륨에 작은에 사용되지만

, 나는 로깅 또는 잠금 ...

은 여기, 그들이 거래에 참여하지 않기 때문에 당신이 당신의 이익을 위해 사용할 수있을 것 같아요 적절한 샘플 코드 :의

--First declare the table variable 
DECLARE @TempTable TABLE 
(
    q VARCHAR(10), 
    w DATETIME, 
    e DATETIME, 
    r DATETIME, 
    t DATETIME, 
    y DATETIME 
) 

... 

WHILE @RowCount < 3000000 
BEGIN 
    ... 

    -- Insert each row into the table variable, no logging is generated here 
    INSERT INTO @TempTable 
    (q 
    ,w 
    ,e 
    ,r 
    ,t 
    ,y) 
    VALUES 
    (REPLICATE('0', 10 - DATALENGTH(@RowString)) + @RowString 
    , @InsertDate 
    ,DATEADD(dd, 1, @InsertDate) 
    ,DATEADD(dd, 2, @InsertDate) 
    ,DATEADD(dd, 3, @InsertDate) 
    ,DATEADD(dd, 4, @InsertDate)) 

    ... 
END 

-- Bulk Insert the generated data, again no logging should be generated here 
INSERT INTO Table_1 WITH(TABLOCK) 
SELECT * FROM @TempTable