SqlBulkCopyを使って高速に大量のテストデータを作成(それでも2時間以上かかっているがな(゚Д゚))
テスト用に1億件分のSQL Serverのデータが欲しくなったので、テストデータ作成プログラムを作ってみたり(・ω・)
普通にINSERTしていくと数百件/秒くらいの速度しか出ないので、SqlBulkCopyを使って高速に作成。
SqlBulkCopyを使うと処理速度は2桁違うわけですが、1億レコードともなるとそれでも2時間以上かかったりして(゚Д゚;)
ちなみにテストプログラムのソースはこんなんです。
static void Main(string[] args) { Stopwatch watch = Stopwatch.StartNew(); SqlBulkCopy sbc = new SqlBulkCopy(Settings.Default.ConnectionString, SqlBulkCopyOptions.TableLock); sbc.DestinationTableName = "Search"; int effected = 0; for( int i = 0; i < 10000; i++ ) { sbc.WriteToServer( new TestDataReader( i * 10000, 10000, words ) ); effected += 10000; Debug.WriteLine( String.Format( "{0, 9} : {1} : {2} tps", effected, watch.Elapsed, (int)( effected / watch.Elapsed.TotalSeconds ) ) ); } }
10,000件のバルクインサートを10,000回実行しています。
テスト用のデータを作成するDataReaderはこんなカンジで。
class TestDataReader : IDataReader { private readonly int max; private int current = 0; public TestDataReader(int start, int limit) { this.current = start; this.max = start + limit; } public int FieldCount { get { return 17; } // 列の数固定 } public bool Read() { return this.current++ < this.max; } public object GetValue(int i) { if ( i == 0 ) { return this.current; } ... } public string GetName(int i) { throw new NotImplementedException(); } ... 後のメソッドはNotImplementedExceptionでOK ... }
GetValue()メソッドでは、列のインデックスによって返すデータを変えています。
テスト用のテーブルはこんな構造のものを使っているんですが。
CREATE TABLE [dbo].[Search]( [Id] [int] NOT NULL, [Flag1] [char](1) NOT NULL, [Flag2] [char](1) NOT NULL, [Flag3] [char](1) NOT NULL, [Flag4] [char](1) NOT NULL, [Flag5] [char](1) NOT NULL, [Flag6] [char](1) NOT NULL, [Flag7] [char](1) NOT NULL, [Flag8] [char](1) NOT NULL, [Data1] [nvarchar](max) NOT NULL, [Data2] [nvarchar](max) NOT NULL, [Data3] [nvarchar](max) NOT NULL, [Data4] [nvarchar](max) NOT NULL, [Data5] [nvarchar](max) NOT NULL, [Data6] [nvarchar](max) NOT NULL, [Data7] [nvarchar](max) NOT NULL, [Data8] [nvarchar](max) NOT NULL, CONSTRAINT [PK_Search] PRIMARY KEY CLUSTERED ( [Id] ASC ) )
Id列には連番を、Flag*列にはRandomで"1"〜"5"までの値を設定。
Data*列には辞書ファイル(約30,000語)からランダムに文字を抽出して繋げて、適当な文章を設定。
品詞までは見ていないので、「大食ブラジャーさすが沿道付きまと嫌い昇天遭遇壇上払い戻し」みたいなおかしな文章ですが(・ω・)