[英]MYSQL Insert very slow
我正在將大約900000行的數據表插入MySQL數據庫,現在13個小時后,我的Programm已插入185000行。 那就是我想慢的^^
這是我的代碼如何將DataTable插入MYSQL DB
//data is typeof DataTable and filled with my data.
using (System.Data.SqlClient.SqlConnection srcConnection = new SqlConnection(Settings.Default.SourceConnection))
using (MySql.Data.MySqlClient.MySqlConnection dstConnection = new MySqlConnection(Settings.Default.TargetConnection))
{
if (dstConnection.State != ConnectionState.Open)
dstConnection.Open();
if (srcConnection.State != ConnectionState.Open)
srcConnection.Open();
var builder = SqlBuilder(tableName, data)
foreach (DataRow toCopy in data)
{
using (var cmdUpdate = builder.GenerateUpdateCommand(dstConnection, toCopy))
{
if (cmdUpdate.ExecuteNonQuery() == 0)
{
using (var cmdInsert = builder.GenerateInsertCommand(dstConnection, toCopy))
{
cmdInsert.ExecuteNonQuery;
}
}
}
}
}
建設者是我自己的班級:
public class SqlBuilder
{
private readonly string _tableName;
private readonly DataColumnCollection _columns;
private readonly List<string> _columnStrings = new List<string>();
private DataColumn _primaryDataColumn;
private readonly Logger _logger = LogManager.GetLogger(typeof(SqlBuilder).FullName);
public SqlBuilder(string tableName, DataTable table)
{
if (tableName == null) throw new ArgumentNullException("tableName");
if (table == null) throw new ArgumentNullException("table");
if (table.PrimaryKey.Count() != 1) throw new ArgumentException("Only one primary key supported", "table");
_tableName = tableName;
_columns = table.Columns;
_primaryDataColumn = table.PrimaryKey[0];
foreach (DataColumn column in _columns)
_columnStrings.Add(column.ColumnName);
}
public SqlBuilder()
{
}
public string TableName
{
get { return _tableName; }
}
public String[] ColumnStrings
{
get { return _columnStrings.ToArray(); }
}
public IDbCommand GenerateCountCommand(IDbConnection con)
{
IDbCommand result = con.CreateCommand();
result.CommandText = String.Format("SELECT COUNT(*) FROM {0}", TableName);
return result;
}
public IDbCommand GenerateDeleteTableCommand(IDbConnection con)
{
IDbCommand result = con.CreateCommand();
result.CommandText = String.Format("DELETE FROM {0}", TableName);
return result;
}
public IDbCommand GenerateDeleteChangeLogTableCommand(IDbConnection con)
{
IDbCommand result = con.CreateCommand();
result.CommandText = String.Format("DELETE FROM ChangeLog");
return result;
}
public String GenerateInsertCommandText()
{
String result;
result = String.Format(
"INSERT INTO {0} ({1}) VALUES ({2})",
TableName,
String.Join(",", _columnStrings.ToArray()),
String.Join(",", _columnStrings.Select(s => "@" + s).ToArray()));
return result;
}
public string GenerateUpdateCommandText()
{
String result;
result = String.Format(
"UPDATE {0} SET {1} WHERE {2}",
TableName,
String.Join(", ", _columnStrings.Where((s =>!_primaryDataColumn.ColumnName.Equals(s))).Select(s => s+"=@" + s).ToArray()),
_primaryDataColumn.ColumnName+"=@"+_primaryDataColumn.ColumnName
);
return result;
}
public string GenerateDeleteCommandText(int id)
{
string result = String.Format("DELETE FROM {0} WHERE {1} = {2}", _tableName , _columnStrings[0], id);
return result;
}
public IDbCommand GenerateInsertCommand(IDbConnection con, DataRow row)
{
IDbCommand result = con.CreateCommand();
result.CommandText = GenerateInsertCommandText();
result = FillParameters(row, result);
if (_logger.IsTraceEnabled) _logger.Trace(result.CommandText);
return result;
}
public IDbCommand GenerateUpdateCommand(IDbConnection connection, DataRow dataRow)
{
IDbCommand result = connection.CreateCommand();
result.CommandText = GenerateUpdateCommandText();
result = FillParameters(dataRow, result);
if (_logger.IsTraceEnabled) _logger.Trace(result.CommandText);
return result;
}
public IDbCommand GenerateDeleteCommand(IDbConnection con, int id)
{
IDbCommand result = con.CreateCommand();
result.CommandText = GenerateDeleteCommandText(id);
return result;
}
private IDbCommand FillParameters(DataRow row, IDbCommand result)
{
foreach (var curColumn in _columnStrings)
{
IDbDataParameter parameter = result.CreateParameter();
parameter.ParameterName = curColumn;
parameter.Value = row[curColumn];
result.Parameters.Add(parameter);
}
return result;
}
}
任何人都知道如何使它更快嗎???
在一條語句中插入幾行,如下所示:
INSERT INTO table (...) VALUES
(values for first record),
(values for second record),
...
您可能會像這樣在一條語句中插入幾十行,具體取決於記錄的大小。
我在類似的參數構建過程中發現的是設置參數的“ SourceColumn” ...在“ FillParameters”方法中,嘗試添加
parameter.SourceColumn = curColumn;
然后,在您的INSERT例程中,
foreach( DataRow )
Build The Insert Command
Execute Insert
改成
Build The Insert Command
ForEach( DataRow )
Execute Insert
這樣,您不必一遍又一遍地構建命令。 該參數將轉到要處理的數據行的源列,並為您拉入。
當我編寫我的版本時,同樣也適用於更新和刪除。 我已經預先構建了命令和參數,並在我正在使用的DataTable期間保留它們。
因此,您實際上可以在foreach(DataRow)之前構建insert和update命令,然后使用它們。 一遍又一遍。 顯然,在假設所有記錄都可以通過之前,請僅測試幾條記錄以確認其是否可以正常使用。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.