C# MYSQL中在表之间移动数据的最佳方法

C# MYSQL中在表之间移动数据的最佳方法,c#,mysql,C#,Mysql,我有一个关于性能的问题。这是我的设想 我有一个MYSQL数据库和一个应用程序,它可以根据查询的条件将记录从一个表移动到另一个表。这样做的方式是: foreach(object obj in list) { string id = obj.ToString().Split(',')[0].Trim(); string query = " insert into old_records select * from testes where id='" +

我有一个关于性能的问题。这是我的设想

我有一个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行,将所有记录从一个表移动到另一个表需要很多时间,特别是通过网络。有没有办法让这更快


我已经做了一些阅读,有几个选项可以处理来自DB的数据,比如数据适配器、读取器、集合和表。在这种情况下,哪一个更快?我应该使用另一种方法吗?

我可能错了,但为了加快速度,您没有什么办法。毕竟,您希望获取整个表数据并将其信息插入到另一个表中。如果您的桌子不小,这个过程将需要一些时间。但是,您可以尝试使用下面的代码。它应该做到这一点,并节省一些时间

INSERT INTO TABLE2 (FIELDNAME_IN_TABLE2, FIELDNAME2_IN_TABLE2)
SELECT FIELDNAME_IN_TABLE1, FIELDNAME2_IN_TABLE1
FROM TABLE1

我看到的两件事是,首先,每次插入都要打开和关闭连接,这通常是最昂贵的操作,所以您不想这样做。您还可以尝试对它们进行批处理,而不是立即进行。当你这样做时,你必须小心,因为事情可能在大更新的中间中断,所以你想在事务中做事情。在不太了解您的数据结构的情况下,我对您的方法进行了重构,一次进行100次批处理。首先创建一个名为moveitems的小助手方法,它接受一个连接和一个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();
}
private static void MoveItems(MySqlConnection conn,List moveList)
{
string query=string.Format(“插入到旧的_记录中,从({0})中id所在的测试中选择*;”+“从({0})中id所在的测试中删除)”,string.Join(“,”,moveList.ToArray());
var cmd=新的MySqlCommand
{
连接=连接,
CommandText=查询
};
cmd.ExecuteNonQuery();
}
接下来,您将更改main方法以打开数据库连接一次,然后每次调用这个方法100个id。此方法将有一个try-catch,因此,如果对MoveItems的调用引发异常,则将在此主方法中捕获该异常

// 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();
    }
}
//using语句将调用您的dispose方法
使用(var conn=new MySqlConnection(connectionString))
{
//打开连接并启动事务
conn.Open();
var事务=conn.BeginTransaction();
//创建一个列表以临时存储ID
列表移动=新列表();
尝试
{
//清理列表,进行修剪,得到所有不为null或空的内容
var cleanList=list.Select(obj=>obj.ToString().Split(',)[0].Trim()).Where(s=>!string.IsNullOrEmpty(s));
//循环浏览干净的列表
foreach(cleanList中的字符串id)
{
//将id添加到移动列表中
移动。添加(“”+id+“”);
//一次100批
如果(moves.Count%100==0)
{
//当我达到100时,执行它们并清除列表
移动项目(连接、移动);
移动。清除();
}
}
//列表计数可能不是n(mod 100),因此请查看是否还有剩余内容
如果(moves.Count>0)
{
移动项目(连接、移动);
移动。清除();
}
//哇!提交事务
Commit();
}
捕获(MySqlException-ex)
{
//哎呀!发生了什么事把所有的东西都滚回去
transaction.Rollback();
控制台写入线(例如消息);
}
最后
{
康涅狄格州关闭();
}
}

你可能得用那100个数字。我记得当我经常使用MySQL时,我看到了执行IN和给它一个Or语句列表(Id='ID1'或Id='ID2'…)之间的一些性能差异。但是执行40条语句或80条语句肯定会有更好的性能,打开数据库连接一次而不是4000次也会有更好的性能。

这会改变吗?通过移动、insert to new和delete OF old?它应该将数据从一个表移动到另一个表,但是它不会删除任何记录。您的第一点是正确的,但您的代码只有在数据库位于同一服务器上时才起作用。如果是通过网络连接的,您需要链接服务器。@gunr217我已经在网络上运行了。。每个记录大约需要2秒钟:(想象一下4000!@TommyNaidich,但是当它被复制到第二个记录时,我还需要从第一个记录中删除它……我需要移动而不是复制。