我对性能有疑问。这是我的情景。
我有一个MYSQL数据库和一个应用程序,它根据查询的条件,不时地将记录从一个表移动到另一个表。这样做的方法是:
foreach(object obj in list)
{
string id = obj.ToString().Split(',')[0].Trim();
string query = " insert into old_records select * from testes where id='" +
id + "';" + " delete from testes where id='" + id +"'";
DB _db = new DB();
_db.DBConnect(query);
这是我连接数据库的方式:
DataTable _dt = new DataTable();
MySqlConnection _conn = new MySqlConnection(connectionString);
MySqlCommand _cmd = new MySqlCommand
{
Connection = _conn,
CommandText = query
};
MySqlDataAdapter _da = new MySqlDataAdapter(_cmd);
MySqlCommandBuilder _cb = new MySqlCommandBuilder(_da);
_dt.Clear();
try
{
_conn.Open();
_cmd.ExecuteNonQuery();
_da.Fill(_dt);
}
catch (MySqlException ex)
{
Console.WriteLine(ex.Message);
}
finally
{
if (_conn != null) _conn.Close();
}
return _dt;
所以我的问题是,我在表中有4000行,并且需要花费大量时间将所有记录从一个表移动到另一个表,特别是通过网络。有没有办法让这更快?
我一直在做一些阅读,有几个选项来处理来自数据库的数据,如数据适配器,阅读器,集和表。对于这种情况哪一个更快?我应该使用不同的方法吗?
答案 0 :(得分:0)
我看到的两件事是,首先你要为每个插件打开和关闭连接,这通常是你最昂贵的操作,所以你不想这样做。您也可以尝试对它们进行批处理,而不是立即进行批处理。当你这样做时,你必须要小心,因为事情可能会在大型更新过程中中断,所以你想要在事务中做事。在不太了解您的数据结构的情况下,我重构了您的方法,一次进行100次批处理。首先创建一个名为move项的小辅助方法,它接受一个连接和一个id列表。不要试试这个,你会明白为什么以后。
注意:此方法不使用参数,我强烈建议您更改它以执行此操作。
private static void MoveItems(MySqlConnection conn, List<string> moveList)
{
string query = string.Format("insert into old_records select * from testes where id IN({0});" + " delete from testes where id IN({0})", string.Join(",", moveList.ToArray()));
var cmd = new MySqlCommand
{
Connection = conn,
CommandText = query
};
cmd.ExecuteNonQuery();
}
接下来,您将更改主方法以打开数据库连接一次,然后一次调用此方法100个ID。这个方法将有一个try catch因此,如果对MoveItems的调用抛出异常,它将被捕获在这个main方法中。
// the using statement will call your dispose method
using (var conn = new MySqlConnection(connectionString))
{
// open the connection and start the transaction
conn.Open();
var transaction = conn.BeginTransaction();
// createa list to temporarily store the ids
List<string> moves = new List<string>();
try
{
// clean the list, do the trim and get everything that's not null or empty
var cleanList = list.Select(obj => obj.ToString().Split(',')[0].Trim()).Where(s => !string.IsNullOrEmpty(s));
// loop over the clean list
foreach (string id in cleanList)
{
// add the id to the move list
moves.Add("'" + id + "'");
// batch 100 at a time
if (moves.Count % 100 == 0)
{
// when I reach 100 execute them and clear the list out
MoveItems(conn, moves);
moves.Clear();
}
}
// The list count might not be n (mod 100) therefore see if there's anything left
if (moves.Count > 0)
{
MoveItems(conn, moves);
moves.Clear();
}
// wohoo! commit the transaction
transaction.Commit();
}
catch (MySqlException ex)
{
// oops! something happened roll back everything
transaction.Rollback();
Console.WriteLine(ex.Message);
}
finally
{
conn.Close();
}
}
您可能必须使用该100号码。我记得当我使用MySQL很多时,我看到在执行IN和给它一个Or语句列表之间存在一些性能差异(Id ='ID1'OR id ='ID2'...)。但执行40个语句或80个语句肯定会有更好的性能,而打开数据库连接一次而不是4000次也应该会给你带来更好的性能。
答案 1 :(得分:-1)
我可能错了,但为了加快速度,你无能为力。毕竟,您希望获取整个表数据并将其信息插入另一个表中。如果你的牌桌不小,那么的过程需要一些时间。但是,您可以尝试使用以下代码。它应该做到这一点并节省一些时间。
INSERT INTO TABLE2 (FIELDNAME_IN_TABLE2, FIELDNAME2_IN_TABLE2)
SELECT FIELDNAME_IN_TABLE1, FIELDNAME2_IN_TABLE1
FROM TABLE1