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

时间:2013-06-02 01:02:02

标签: 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='" + 
                    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行,并且需要花费大量时间将所有记录从一个表移动到另一个表,特别是通过网络。有没有办法让这更快?

我一直在做一些阅读,有几个选项来处理来自数据库的数据,如数据适配器,阅读器,集和表。对于这种情况哪一个更快?我应该使用不同的方法吗?

2 个答案:

答案 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