插入多行的最快方法

时间:2015-11-03 11:20:11

标签: c# mysql sql .net database

我有DataTable,其中包含数十万行。在我的程序过程中,我向这个DataTable添加了几千行,这些行也需要添加到数据库中。我想尽快插入它们,而不是为每条记录创建一个INSERT语句。 MySQL LOAD INTO命令不合适,因为我不想涉及任何外部CSV文件。

到目前为止我所做的是使用MySqlDataAdapter并致电'更新'只有插入更改的方法,如下所示:

MySqlCommandBuilder commandBuilder = new MySqlCommandBuilder(adapter);
adapter.InsertCommand = commandBuilder.GetInsertCommand();
adapter.Update(myDataTable);

这也运行缓慢,所以我怀疑它们也是一次插入一行。我有什么选择?构建一个包含其中所有值的长INSERT语句,唯一的方法是什么?

5 个答案:

答案 0 :(得分:6)

插入如下值: -

INSERT INTO tbl_name
    (a,b,c)
VALUES
    (1,2,3),
    (4,5,6),
    (7,8,9);
  

要优化插入速度,请将许多小型操作合并为一个   大手术。

答案 1 :(得分:2)

我看到的唯一解决方案是:

1)将DataTable转换为csv->你可以谷歌吧。

2)将其保存在临时目录的服务器端。

3)在这里使用MySqlBulkLoader link来撰写有关它的文章。加载保存在临时目录中的文件。

4)之后从temp目录中删除文件。

答案 2 :(得分:0)

我不知道这是一个带参数的好方法,但效果很好 该方法接收“ParamDbList”列表(ParamDB的集合)并且每1000个寄存器或1900个参数(2000的限制)插入行。只需根据您的驱动器进行调整

  public bool InsertBatch(System.Collections.Generic.List<ParamDbLIST> dados, string tabela)
    {
        if (dados.Count == 0)
            return true;

        string campos = "";
        dados[0].ForEach(delegate(ParamDB p)
        {
            campos += (campos == "" ? "" : ", ") + "@" + p.sNOME + "#N#";
        });

        bool resultado = true;
        //Insere de 999 a 999, que é o máximo q o sql server permite por vez
        //Maximo de 2000 parametros
        int k = 0;
        while (k < dados.Count)
        {
            this.sql = new StringBuilder();
            List<String> vals = new List<string>();
            ParamDbLIST parametros_insert = new ParamDbLIST();
            int c_sqls = 0;
            int c_parametros = 0;
            while (k < dados.Count && c_sqls < 1000 && c_parametros < 1900)
            {
                c_sqls++;
                vals.Add("(" + campos.Replace("#N#", c_sqls.ToString()) + ")");
                foreach (ParamDB p in dados[k])
                {

                    p.sNOME += c_sqls.ToString();
                    parametros_insert.Add(p);
                    c_parametros++;
                }
                k++;
            }

            this.sql.Append("INSERT INTO " + tabela + "(" + campos.Replace("#N#", String.Empty).Replace("@", String.Empty) + ") VALUES " + String.Join(",", vals));

            resultado = resultado && this.RunSQL(sql.ToString(), parametros_insert);

        }

        return resultado;
    }






public class ParamDbLIST : System.Collections.ObjectModel.Collection<ParamDB>
{/*I have other stuff here, but this will work*/}

   public class ParamDB
{
    public string sNOME { get; set; }
    public Object sVALOR { get; set; }}

记住方法 INSERT INTO tbl_name     (A,B,C) VALUES     (1,2,3),     (4,5,6),     (7,8,9); 每个命令限制为1000行。

我认为这里做的好事就是使用交易(为了安全)

您应该更改的方法是RunSQL

如果可以优化此方法,请告诉我

答案 3 :(得分:0)

不确定MySQL,但我发现使用sql server到目前为止最快的插入方式与@Rahautos类似,但是将值列表分开到单独的查询中。 我知道这听起来很奇怪但是这个速度提高了10倍,从每秒12到12000次插入。 不确定区别是什么。 而且交易也非常有用。

INSERT INTO tbl_name
    (a,b,c)
VALUES
    (1,2,3);
INSERT INTO tbl_name
    (a,b,c);
VALUES
    (4,5,6);
INSERT INTO tbl_name
    (a,b,c);
VALUES
    (7,8,9);

示例代码

using System;
using System.Collections.Generic;
using System.Data.SqlClient;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApplication2
{
    class Program
    {
        static void Main(string[] args)
        {
            var constring = (new SqlConnectionStringBuilder
            {
                DataSource = "someserver",
                InitialCatalog = "12trunk",
                IntegratedSecurity = true
            }).ToString();
            using (var con = new SqlConnection(constring))
            {
                con.Open();
                using (var trans = con.BeginTransaction(isolationLevel: System.Data.IsolationLevel.ReadUncommitted) as SqlTransaction)
                using (var cmd = new SqlCommand())
                {
                    cmd.Transaction = trans;
                    cmd.Connection = con;
                    var start = DateTime.Now;
                    Console.WriteLine("Start = " + start);
                    const int inserts = 100000;
                    var builder = new StringBuilder();
                    cmd.CommandText = "delete from test";                    
                    for (int i = 0; i < inserts; i++)
                    {
                        Guid[] guids = new Guid[7];
                        for (int j = 0; j < 7; j++)
                        {
                            guids[j] = Guid.NewGuid();
                        }
                        var sql = $"insert into test (f0, f1, f2, f3, f4, f5, f6) values ('{guids[0]}', '{guids[1]}', '{guids[2]}','{guids[3]}', '{guids[4]}', '{guids[5]}', '{guids[6]}');\n";
                        builder.Append(sql);
                        if (i % 1000 == 0)
                        {
                            cmd.CommandText = builder.ToString();
                            cmd.ExecuteNonQuery();
                            builder.Clear();
                        }

                    }
                    cmd.CommandText = builder.ToString();
                    cmd.ExecuteNonQuery();
                    trans.Commit();
                    var ms = (DateTime.Now - start).TotalMilliseconds;
                    Console.WriteLine("Ms to run = " + ms);
                    Console.WriteLine("inserts per sec = " + inserts / (ms / 1000));
                    Console.ReadKey();
                }
            }
        }
    }
}

答案 4 :(得分:0)

我不确定MYSQl。 但是在MSSql Server中,在这种情况下,我们使用XML。 我们创建一个包含大量数据的xml,然后在数据库中使用Insert With Xml。

INSERT INTO [TBL_USER_INFO](NAME, EMAIL)
   SELECT
      Result.value('value','varchar(25)') as NAME,
      Result.value('value','varchar(50)') as EMAIL
   FROM 
      @input.nodes('/EmployeList/Employee') AS ABCD(Result)