せっかく、最強.NET開発PCにSSDを入れたので、SQL Serverがどれくらい早くなるか計測してみます。つーか、もともとその目的もあって、SSD にしています。大容量の SSD はそれなりにお高いので、本当なら 64GB ぐらいの安めのを買って試してみたいところなのですが、まだ買ってないので。
PLEXTRO PX-512M5P
http://www.goplextor.com/jp/index.php/m5-pro
WDC WD20EZRX-00DC0B0 1TB
という WD にあまりに不利な状況なのですが…まあ、ひと昔前の HDD と最新の SSD を比較するということでやってみます。状況としては、昔の HDD に SQL Server をがりがりやってチューニングして頑張って、という状況だけど、最近データアクセスが遅くて困る。となると、もっとチューニングをするのか、CPU を変えるのか、ソフトウェアをリプレースするのか?と色々考えるけども、HDD から SSD にデータベースを乗せ換えるだけでも十分じゃない?ってところです。
以下、100万件のWEBアクセスログを、BulkCopy でインサートして計測しています。100万件とは言いますが、実は大したことがなくて、実際に業務で扱うデータは1億件ぐらいと桁が2桁ぐらい違いますよね。以前は、この100万件扱うのにひいこら言っていたはずなんですが、CPU とメモリの関係なのか、結構スムースに動きます。なので、相対値としてみてください。
SSD にバルクインサート中
100万件インサートで 7.8秒
HDD にバルクインサート中
100万件インサートで 32.1秒
実測値で5倍ぐらいの違いが出ます。これは、大量のデータインサートなので、状況が特別なのですが、書き込みの場合でも SSD のほうが遥かに早い。
で、別途読み込み(SELECT)をやってみたのですが、こっちのほうはディスクキャッシュが効いていると、どちらも .3 秒とかで返ってくるので比較になりません。当然、インデックスがない状態でこれですから。SELECT のほうは、別途計測方法を考えてリトライしましょう。
■実験ソース
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | void GoBlukCopy( string CNSTR) { DataTable dt = _dt; SqlConnection cn = new SqlConnection(CNSTR); SqlBulkCopy bc = new SqlBulkCopy(cn); DateTime start = DateTime.Now; bc.BulkCopyTimeout = 0; bc.DestinationTableName = "logs" ; cn.Open(); bc.WriteToServer(dt); cn.Close(); DateTime end = DateTime.Now; label2.Text = string .Format( "BulkCopy完了 {0:#.0} sec" , ((TimeSpan)(end - start)).TotalSeconds); } |
ついでにアクセスログから DataTable を作るところも。非同期を使っているので、別の記事にでも解説を。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 | DataTable _dt; int _count; bool _completed; /// <summary> /// ファイルから読み込み /// </summary> /// <returns></returns> public async Task<DataTable> MakeDataTable() { DataTable dt = new DataTable(); dt.Columns.Add( new DataColumn( "dt" , typeof ( string ))); dt.Columns.Add( new DataColumn( "code" , typeof ( string ))); dt.Columns.Add( new DataColumn( "ip" , typeof ( string ))); dt.Columns.Add( new DataColumn( "req" , typeof ( string ))); dt.Columns.Add( new DataColumn( "url" , typeof ( string ))); _completed = false ; await Task.Factory.StartNew( () => { var sr = System.IO.File.OpenText( @"D:sitelogsout3.csv" ); _count = 0; while (sr.EndOfStream == false ) { string line = sr.ReadLine(); string [] v = line.Split( new string [] { "t" }, StringSplitOptions.None); DataRow row = dt.NewRow(); dt.Rows.Add(row); row[ "dt" ] = v[0]; row[ "code" ] = v[1]; row[ "ip" ] = v[2]; row[ "req" ] = v[3]; row[ "url" ] = v[4]; _count++; } sr.Close(); _completed = true ; _dt = dt; }); return dt; } private void button2_Click( object sender, EventArgs e) { Task t1 = MakeDataTable(); Task t2 = Task.Factory.StartNew( async () => { while (_completed == false ) { await Task.Delay(500); label2.Invoke((MethodInvoker)(() => label2.Text = string .Format( "{0} 件読み込み中" , _count))); } label2.Invoke((MethodInvoker)(() => label2.Text = string .Format( "{0} 件読み込み完了" , _count))); }); } |