【问题标题】:Write a large datatable to mysql database c#将大数据表写入mysql数据库c#
【发布时间】:2015-10-12 19:41:05
【问题描述】:

我需要一些帮助。我正在将相当大的数据记录写入远程 MySQL 数据库。记录数从 400k 到超过 1M。

我正在做的是

  1. 将一组记录从一个数据库收集到一个数据表中。

  2. 然后,在我想将数据写入不同的 MySQL 数据库之前,我会对数据表执行一些处理。

  3. 选择和插入实际上非常快,但是为了执行数据的插入我正在通过遍历数据表来创建一个“INSERT INTO...”查询字符串。这需要永远,并且会延迟写出该数据的过程。

我知道这是一个丑陋的解决方案,但我在搜索互联网时找不到更优雅的东西,尽管它可能在那里。

任何帮助将不胜感激。

【问题讨论】:

  • 您是在创建一个插入语句,还是逐行遍历数据表,为每一行创建和执行插入?
  • 我正在为数据表中的所有数据创建一个插入查询。
  • @Rabid_eeryore 另外,在操作过程中与远程数据库的通信通道中断的情况如何处理?
  • 目前我没有。在担心事务完整性之前,我首先尝试解决插入速度慢的问题。
  • 这里的人好像误会了。尝试通过迭代数据表来创建插入查询(用于远程数据库)时会产生问题。

标签: c# mysql


【解决方案1】:

我碰巧遇到了同样的问题,为此写了一个小助手方法。 您可以在我的博客https://randomlol.de/2014/05/29/c-datatable-to-mysql/

中找到解决方案
/*
* ----------------------------------------------------------------------------
* "THE BEER-WARE LICENSE" (Revision 42):
* <fg@code-works.de> wrote this file. As long as you retain this notice you
* can do whatever you want with this stuff. If we meet some day, and you think
* this stuff is worth it, you can buy me a beer in return. Frank Gehann
* ----------------------------------------------------------------------------
*/

using System;
using System.Text;
using System.Data;
using MySql.Data.MySqlClient;

namespace DB
{
    class DBHelper
    {
        /// <summary>
        /// Creates a multivalue insert for MySQL from a given DataTable
        /// </summary>
        /// <param name="table">reference to the Datatable we're building our String on</param>
        /// <param name="table_name">name of the table the insert is created for</param>
        /// <returns>Multivalue insert String</returns>
        public static String BulkInsert(ref DataTable table, String table_name)
        {
            try
            {
                StringBuilder queryBuilder = new StringBuilder();
                DateTime dt;

                queryBuilder.AppendFormat("INSERT INTO `{0}` (", table_name);

                // more than 1 column required and 1 or more rows
                if (table.Columns.Count > 1 && table.Rows.Count > 0)
                {
                    // build all columns
                    queryBuilder.AppendFormat("`{0}`", table.Columns[0].ColumnName);

                    if (table.Columns.Count > 1)
                    {
                        for (int i = 1; i < table.Columns.Count; i++)
                        {
                            queryBuilder.AppendFormat(", `{0}` ", table.Columns[i].ColumnName);
                        }
                    }

                    queryBuilder.AppendFormat(") VALUES (", table_name);

                    // build all values for the first row
                    // escape String & Datetime values!
                    if (table.Columns[0].DataType == typeof(String))
                    {
                        queryBuilder.AppendFormat("'{0}'", MySqlHelper.EscapeString(table.Rows[0][table.Columns[0].ColumnName].ToString()));
                    }
                    else if (table.Columns[0].DataType == typeof(DateTime))
                    {
                        dt = (DateTime)table.Rows[0][table.Columns[0].ColumnName];
                        queryBuilder.AppendFormat("'{0}'", dt.ToString("yyyy-MM-dd HH:mm:ss"));
                    }
                    else if (table.Columns[0].DataType == typeof(Int32))
                    {
                        queryBuilder.AppendFormat("{0}", table.Rows[0].Field<Int32?>(table.Columns[0].ColumnName) ?? 0);
                    }
                    else
                    {
                        queryBuilder.AppendFormat(", {0}", table.Rows[0][table.Columns[0].ColumnName].ToString());
                    }

                    for (int i = 1; i < table.Columns.Count; i++)
                    {
                        // escape String & Datetime values!
                        if (table.Columns[i].DataType == typeof(String))
                        {
                            queryBuilder.AppendFormat(", '{0}'", MySqlHelper.EscapeString(table.Rows[0][table.Columns[i].ColumnName].ToString()));
                        }
                        else if (table.Columns[i].DataType == typeof(DateTime))
                        {
                            dt = (DateTime)table.Rows[0][table.Columns[i].ColumnName];
                            queryBuilder.AppendFormat(", '{0}'", dt.ToString("yyyy-MM-dd HH:mm:ss"));

                        }
                        else if (table.Columns[i].DataType == typeof(Int32))
                        {
                            queryBuilder.AppendFormat(", {0}", table.Rows[0].Field<Int32?>(table.Columns[i].ColumnName) ?? 0);
                        }
                        else
                        {
                            queryBuilder.AppendFormat(", {0}", table.Rows[0][table.Columns[i].ColumnName].ToString());
                        }
                    }

                    queryBuilder.Append(")");
                    queryBuilder.AppendLine();

                    // build all values all remaining rows
                    if (table.Rows.Count > 1)
                    {
                        // iterate over the rows
                        for (int row = 1; row < table.Rows.Count; row++)
                        {
                            // open value block
                            queryBuilder.Append(", (");

                            // escape String & Datetime values!
                            if (table.Columns[0].DataType == typeof(String))
                            {
                                queryBuilder.AppendFormat("'{0}'", MySqlHelper.EscapeString(table.Rows[row][table.Columns[0].ColumnName].ToString()));
                            }
                            else if (table.Columns[0].DataType == typeof(DateTime))
                            {
                                dt = (DateTime)table.Rows[row][table.Columns[0].ColumnName];
                                queryBuilder.AppendFormat("'{0}'", dt.ToString("yyyy-MM-dd HH:mm:ss"));
                            }
                            else if (table.Columns[0].DataType == typeof(Int32))
                            {
                                queryBuilder.AppendFormat("{0}", table.Rows[row].Field<Int32?>(table.Columns[0].ColumnName) ?? 0);
                            }
                            else
                            {
                                queryBuilder.AppendFormat(", {0}", table.Rows[row][table.Columns[0].ColumnName].ToString());
                            }

                            for (int col = 1; col < table.Columns.Count; col++)
                            {
                                // escape String & Datetime values!
                                if (table.Columns[col].DataType == typeof(String))
                                {
                                    queryBuilder.AppendFormat(", '{0}'", MySqlHelper.EscapeString(table.Rows[row][table.Columns[col].ColumnName].ToString()));
                                }
                                else if (table.Columns[col].DataType == typeof(DateTime))
                                {
                                    dt = (DateTime)table.Rows[row][table.Columns[col].ColumnName];
                                    queryBuilder.AppendFormat(", '{0}'", dt.ToString("yyyy-MM-dd HH:mm:ss"));
                                }
                                else if (table.Columns[col].DataType == typeof(Int32))
                                {
                                    queryBuilder.AppendFormat(", {0}", table.Rows[row].Field<Int32?>(table.Columns[col].ColumnName) ?? 0);
                                }
                                else
                                {
                                    queryBuilder.AppendFormat(", {0}", table.Rows[row][table.Columns[col].ColumnName].ToString());
                                }
                            } // end for (int i = 1; i < table.Columns.Count; i++)

                            // close value block
                            queryBuilder.Append(")");
                            queryBuilder.AppendLine();

                        } // end for (int r = 1; r < table.Rows.Count; r++)

                        // sql delimiter =)
                        queryBuilder.Append(";");

                    } // end if (table.Rows.Count > 1)

                    return queryBuilder.ToString();
                } 
                else
                {
                    return "";
                } // end if(table.Columns.Count > 1 && table.Rows.Count > 0)
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
        }
    }
}

【讨论】:

  • 我需要删除 queryBuilder.AppendFormat(", {0}", table.Rows[0][table.Columns[i].ColumnName].ToString()); 的逗号它奏效了
【解决方案2】:

为了提高插入的性能,我建议使用BULK INSERT 方法。

【讨论】:

    【解决方案3】:

    如果我理解正确,您想提高插入性能,所以在我看来(可能不是最佳答案)您可以将数据表写入 csv 文件,然后使用 mysqlbulkloader 将其读入数据库。 mysqlbuldloader 带有用于 .NET 的 MySQL 连接器

    【讨论】:

    • 你的理解是正确的。这似乎有点沉重,我在互联网上的其他地方看到并避免了它。不过我会试一试的。
    • 我认为这个文件写入操作然后使用批量插入仍然会更快。
    【解决方案4】:

    我的意见是,由于您使用的是数据表,因此插入数据的最佳方式是使用 BulkInsert。这将帮助您执行更快速的操作

    【讨论】:

      猜你喜欢
      • 2011-12-04
      • 2011-12-11
      • 1970-01-01
      • 2021-03-02
      • 2013-07-22
      • 2016-10-06
      • 2016-04-08
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多