我在C#中将一堆行加载到MySql中。在MS Sql中,我可以将DataReader提供给SqlBulkCopy,但MySqlBulkCopy仅将自身表示为来自文件的批量加载的引导程序。
因此,我目前的解决方案是在事务处理循环中使用准备好的命令。
使用DataReader源是否有更快的方法来完成MySql的批量加载?
这是代码。
public override void WriteToServer(IDataReader reader)
{
const string insertFormat = "insert into `{3}`.`{0}` ({1}) values ({2});";
string names = string.Join(",",
_command.Parameters.Cast<MySqlParameter>().Select(p => p.ParameterName).ToArray());
string vals = string.Join(",",
_command.Parameters.Cast<MySqlParameter>().Select(p => "?" + p.ParameterName).
ToArray());
_command.CommandText = string.Format(insertFormat, _table, names, vals, _schema);
int reportCounter = 0;
int totalRecords = 0;
bool finished = false;
using (var connection = new MySqlConnection(_source))
{
connection.Open();
_command.Connection = connection;
_command.Prepare();
while (!finished)
{
using (MySqlTransaction dbTrans = connection.BeginTransaction(IsolationLevel.ReadUncommitted))
{
for (int i = 0; i < BatchSize; i++)
{
if (!reader.Read())
{
finished = true;
break;
}
try
{
for (int p = 0; p < _command.Parameters.Count; p++)
{
_command.Parameters[p].Value = reader.GetValue(p);
}
_command.ExecuteNonQuery();
}
catch (Exception ex)
{
Trace.WriteLine(ex.Message);
}
reportCounter++;
totalRecords++;
if (reportCounter >= NotifyAfter)
{
reportCounter = 0;
OnSqlRowsCopied(new SqlRowsCopiedEventArgs(totalRecords));
}
}
dbTrans.Commit();
}
}
}
}
答案 0 :(得分:3)
除了使用“文件中的LOAD DATA”之外,MySQL还有一个非SQL标准的“批量插入”机制,您可以在其中指定要插入的多个“值”:http://dev.mysql.com/doc/refman/5.0/en/insert.html
INSERT INTO TABLE x (a,b,c,e,d,f,g,...)
VALUES ( ?, ?, ?, ?, ?, ?, ?, ?, ... )
, ( ?, ?, ?, ?, ?, ?, ?, ?, ... )
, ( ?, ?, ?, ?, ?, ?, ?, ?, ... )
, ( ?, ?, ?, ?, ?, ?, ?, ?, ... )
, ( ?, ?, ?, ?, ?, ?, ?, ?, ... )
此示例将插入5行的“块”。您可以使用'prepared'语句来提高每行生成的sql的性能。这方面的缺点是,在您加载了数百万条记录之后,您可能只剩下3行要插入。您需要使用3行插入重新准备SQL。除非你使用'INSERT IGNORE',否则不要试图对缺少的第4和第5条记录使用NULL,但这比典型插入要慢。重新准备非常快,值得结果。
我们有一个表格,其插入块大小为200多行!每个插入的最大行数基于操作系统认为是mmap()和malloc()之间的切换点的内存大小。对于Solaris 10,我们使用“4096 / rows_size = rows_per_insert”。有关此问题的某个mysql错误与read_buffer_size松散相关。