SQL Serverに1億件のテストデータを高速に作成する

SQL Serverに1億件を超える大量のテストデータを作成する必要がありできるだけ高速な方法を調べてみた。

ストプロを試してみる

まずはストプロを作成してどの程度になる確認してみる。単純にループを回してINSERTを1件づつ行う方法でまずは100万件で試してみる。

ALTER PROCEDURE dbo.CreateData
AS
	SET NOCOUNT ON 
	DECLARE @RowCount INT
	SET @RowCount = 0
	WHILE @RowCount < 1000000
	BEGIN
		INSERT INTO TestTable
		VALUES
			(@RowCount, 'DATA' + right('0000000000' + convert(varchar, @RowCount), 10))
		SET @RowCount = @RowCount + 1
	END
	RETURN

計測すると7分5秒。1億件作るためには700分以上かかってしまう。
今回ノートPCでの計測なのでサーバーだともう少し高速になると思うが、別の方法を考える必要がありそう。

バルクコピーを試してみる

SQL文ではなくSQLServerのバルクコピーを使ってみる。C#からはSqlBulkCopyクラスを使って利用できる。SqlBulkCopyを使って高速に大量のテストデータを作成を参考に実装してみた。

class Program
{
    static void Main(string[] args)
    {
        Stopwatch sw = Stopwatch.StartNew();
        SqlBulkCopy bulk = new SqlBulkCopy(Settings.Default.MillionDataConnectionString);
        bulk.DestinationTableName = "TestTable";
        bulk.WriteToServer(new TestTableDataReader());
        Console.WriteLine(sw.Elapsed);
    }
}

class TestTableDataReader : IDataReader
{
    private int rowCount = 0;
    public int FieldCount { get { return 2; }  }
    public bool Read()
    {
        return this.rowCount++ < 1000000;
    }
    public object GetValue(int i)
    {
        if (i == 0) return this.rowCount;
        return string.Format("DATA{0:0000000000}", rowCount);
    }
    −−−以下略−−−

計測すると約11秒、先ほどの約50分の1。1億件作るためには18分で実用になりそう。

大きなSELECTデータを作ってINSERTする

もっと良い方法はないか探していると、T-SQL – 1 million records in 1 second(1秒で100万レコード)という記事を見つけた。このSQL文を実行すると指定した件数分のレコードが1から順番に作成される。この作成されたレコードをINSERTするようにSQLを変更して試してみる。

Declare @p_NumberOfRows Bigint 
Select @p_NumberOfRows=1000000; 
With Base As
  (
    Select 1 as n
    Union All
    Select n+1 From Base Where n < Ceiling(SQRT(@p_NumberOfRows))
  ),
  Expand As
  (
    Select 1 as C From Base as B1, Base as B2
  ),
  Nums As
  (
    Select Row_Number() OVER(ORDER BY C) As n From Expand
  )
INSERT INTO TestTable 
  Select n, 'DATA' + right('0000000000' + convert(varchar, n), 10)
    from Nums  Where n<=@p_NumberOfRows
OPTION (MaxRecursion 0); 

計測すると約5秒。1億件作るためには8分ちょっとの予想、これはかなり高速なのかも。
実際に1億件作成してみようと思いますが、ノートPCのDISK容量があまりないので1000万件で試したところほぼ予想通りの57秒だった。