web-dev-qa-db-ja.com

DataTableをMySQLに一括コピーする(System.Data.SqlClient.SqlBulkCopyと同様)

プログラムをMicrosoft SQL ServerからMySQLに移行しています。一括コピーに関する1つの問題を除いて、すべてがうまく機能します。

MS SQLを使用したソリューションでは、コードは次のようになります。

connection.Open();
SqlBulkCopy bulkCopy = new SqlBulkCopy(connection);
bulkCopy.DestinationTableName = "testTable";
bulkCopy.WriteToServer(rawData);

ここで、MySQLに対して同様のことを実行しようとします。パフォーマンスが悪いと思うので、DataTableをCSVファイルに書き込み、そこからMySqlBulkLoaderクラスを使用して挿入を行いたくありません。

任意の助けをいただければ幸いです。

15
Michael Schegg

パフォーマンスが悪いと思うので、DataTableをCSVファイルに書き込み、そこからMySqlBulkLoaderクラスを使用して挿入を行いたくありません。

根拠のない仮定に基づいて可能な解決策を除外しないでください。 Transaction内の標準のMySqlDataAdapter#Update()を使用して、System.Data.DataTableからMySQLテーブルへの100,000行の挿入をテストしました。実行には常に約30秒かかりました。

using (MySqlTransaction tran = conn.BeginTransaction(System.Data.IsolationLevel.Serializable))
{
    using (MySqlCommand cmd = new MySqlCommand())
    {
        cmd.Connection = conn;
        cmd.Transaction = tran;
        cmd.CommandText = "SELECT * FROM testtable";
        using (MySqlDataAdapter da = new MySqlDataAdapter(cmd))
        {
            da.UpdateBatchSize = 1000;
            using (MySqlCommandBuilder cb = new MySqlCommandBuilder(da))
            {
                da.Update(rawData);
                tran.Commit();
            }
        }
    }
}

UpdateBatchSizeにいくつかの異なる値を試しましたが、それらは経過時間に大きな影響を与えるようには見えませんでした。)

対照的に、MySqlBulkLoaderを使用する次のコードは、実行に5〜6秒しかかかりません...

string tempCsvFileSpec = @"C:\Users\Gord\Desktop\dump.csv";
using (StreamWriter writer = new StreamWriter(tempCsvFileSpec))
{
    Rfc4180Writer.WriteDataTable(rawData, writer, false);
}
var msbl = new MySqlBulkLoader(conn);
msbl.TableName = "testtable";
msbl.FileName = tempCsvFileSpec;
msbl.FieldTerminator = ",";
msbl.FieldQuotationCharacter = '"';
msbl.Load();
System.IO.File.Delete(tempCsvFileSpec);

... DataTableから一時CSVファイルに100,000行をダンプする時間( this と同様のコードを使用)、そのファイルからの一括読み込み、その後のファイルの削除を含みます。

13
Gord Thompson

BulkOperation NuGetパッケージのいずれかを使用すると、これを簡単に行うことができます。

https://www.nuget.org/packages/Z.BulkOperations/2.14.3/ のパッケージを使用した例を次に示します。

using Z.BulkOperations;

…….

MySqlConnection conn = DbConnection.OpenConnection();
DataTable dt = new DataTable("testtable");
MySqlDataAdapter da = new MySqlDataAdapter("SELECT * FROM testtable", conn);
MySqlCommandBuilder cb = new MySqlCommandBuilder(da);
da.Fill(dt);

使用する代わりに

......
da.UpdateBatchSize = 1000;
......
da.Update(dt)

ちょうど2行に従う

var bulk = new BulkOperation(conn);
bulk.BulkInsert(dt);

最初にDataTableから一時的なCSVファイルに100,000行をダンプせずに、DataTable全体をMySQLにコピーするのに5秒しかかかりません。

2
alex