SSDにするとBlukcopyは5倍ぐらい早くなる

せっかく、最強.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秒
20130408_02
HDD にバルクインサート中
20130408_03
100万件インサートで 32.1秒

20130408_04

実測値で5倍ぐらいの違いが出ます。これは、大量のデータインサートなので、状況が特別なのですが、書き込みの場合でも SSD のほうが遥かに早い。

で、別途読み込み(SELECT)をやってみたのですが、こっちのほうはディスクキャッシュが効いていると、どちらも .3 秒とかで返ってくるので比較になりません。当然、インデックスがない状態でこれですから。SELECT のほうは、別途計測方法を考えてリトライしましょう。

■実験ソース

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 を作るところも。非同期を使っているので、別の記事にでも解説を。

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)));
    });
}
カテゴリー: C#, データベース, パフォーマンス パーマリンク