SSDにするとBlukcopyは5倍ぐらい早くなる – Moonmile Solutions Blog と MySQLでHDD/SSDのアクセススピードを比較する – Moonmile Solutions Blog の続きです。@h141gm さんから、MySqlBulkLoader もあるよ、ということなので再実験。さすがに、insert の連続では SQL Server との比較が無理があるし、insert の連続が SSD の処理に追い付いているかどうかもあやしいので、ちょっと仕切り直します。
# my.ini の値は、xampp の吊るしのまま使っています。ひとまず既製品状態でどのくらいの差がでるのかな?ってことで。チューニングするとどの位なのか?ってのも興味あるところなのですが「チューニングしなくても、SSD を換装すれば「手軽に」早くなる、ってのが理想的なのです。
例によって、100万件のアクセス生ログを読み込せます。
■MySqlBulkLoader で insert する
SSD の BulkLoader で、11.8 sec
HDD で 26.8 sec
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
2回目以降はキャッシュが効くのかと思っていたら、SSD で 5.0 sec、HDD で 7.9 sec と変わりません。このあたりはチューニングで変わるのかもしれません。
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); }