MySQLでMySqlBulkLoaderのスピードをHDD/SSDで比較する

SSDにするとBlukcopyは5倍ぐらい早くなる – Moonmile Solutions BlogMySQLでHDD/SSDのアクセススピードを比較する – Moonmile Solutions Blog の続きです。@h141gm さんから、MySqlBulkLoader もあるよ、ということなので再実験。さすがに、insert の連続では SQL Server との比較が無理があるし、insert の連続が SSD の処理に追い付いているかどうかもあやしいので、ちょっと仕切り直します。

# my.ini の値は、xampp の吊るしのまま使っています。ひとまず既製品状態でどのくらいの差がでるのかな?ってことで。チューニングするとどの位なのか?ってのも興味あるところなのですが「チューニングしなくても、SSD を換装すれば「手軽に」早くなる、ってのが理想的なのです。

例によって、100万件のアクセス生ログを読み込せます。

■MySqlBulkLoader で insert する

SSD の BulkLoader で、11.8 sec

image

image

HDD で 26.8 sec

image

image

SSD のほうが HDD よりも 2.5 倍ぐらい早くなっています。

BulkCopy/BulkLoader SSD HDD
SQL Server 7.8 sec 32.1 sec
MySQL 11.8 sec 26.8 sec

SQL Server の BulkCopy は、メモリ上の DataTable から一気に突っ込むので、ファイルを解析しながロードする MySQL の BulkLoader よりも早いのは当然…なのですが、ええ、HDD のほうが逆転しているけど無視で(苦笑)。ロードするファイル自体は SSD に置いてあるので、このファイルが HDD 上にあると MySQL の BulkLoader のほうが遅くなる可能性があります。この計測からいけば、単純に HDD から SSD に切り替えただけでも、2.5 倍から 4 倍ぐらいの効果がありますね、ってことが分かります。

■500万件のデータから SELECT する

SQL Server のデータベースファイルを SSD に移す – Moonmile Solutions Blog と似たようなクエリを使って計測します。

初回の SELECT が、SSD で 5.1 sec、HDD が 7.9 sec

imageimage

2回目以降はキャッシュが効くのかと思っていたら、SSD で 5.0 sec、HDD で 7.9 sec と変わりません。このあたりはチューニングで変わるのかもしれません。

imageimage

SSD初回 SSD二回目 HDD初回 HDD2回目
SQL Server 4.6 sec 0.4 sec 15.1 sec 0.4 sec
MySQL 5.1 sec 5.1 sec 7.9 sec 7.9 sec

使用メモリを見ると、SQL Server は2回目のときに 4GB 程度取っていますが、MySQL の場合は 36 MB 程度と謙虚です。がっつりメモリを割り当ててやれば、MySQL の場合も超早になるのかなと。ただし、SQL Server + HDD の組み合わせが遅すぎですよね…MySQL が早いのかもしれませんが。

この結果を見ると、SELECT の場合は、HDD から SSD に換装してもあまりメリットがないかな、って感じもします。この場合は、単純なアクセスログでワンテーブルの検索でしかないので、複雑な join をしたときにはどうか分かりませんが、大量データ&単純な全検索のパターンだと、SELECT 時の恩恵はあまりないかもしれません。ええと、チューニングすれば別のような気もしますが。

■実験コードの抜粋

MySqlBulkLoader を利用

void GoBulkLoad(string CNSTR)
{
    MySqlConnection cn = new MySqlConnection(CNSTR);
    MySqlBulkLoader bl = new MySqlBulkLoader(cn);
    bl.TableName = "logs";
    bl.FieldTerminator = "t";  // タブ区切り
    bl.LineTerminator = "n";   // 改行
    bl.FileName = @"D:sitelogsout.csv";

    DateTime start = DateTime.Now;

    cn.Open();
    bl.Load();
    cn.Clone();

    DateTime end = DateTime.Now;
    label2.Text = string.Format("BulkCopy完了 {0:#.0} sec",
        ((TimeSpan)(end - start)).TotalSeconds);
}

MySqlCommand で検索

void GoSelect(string CNSTR)
{
    var ip = textBox1.Text;
    var cn = new MySqlConnection(CNSTR);
    var cmd = new MySqlCommand(
        "select count(*) from logs where ip = @ip", cn);
    cmd.Parameters.Add(new MySqlParameter("@ip", ip));
    DateTime start = DateTime.Now;
    cn.Open();
    object cnt = cmd.ExecuteScalar();
    cn.Clone();

    DateTime end = DateTime.Now;
    label4.Text = string.Format("検索結果 {0}件 {1:#.0} sec", cnt,
        ((TimeSpan)(end - start)).TotalSeconds);
}
カテゴリー: MySQL, パフォーマンス パーマリンク