快速向SQL Server中插入200万行

Wad*_*hal 67 c# database sql-server asp.net ado.net

我必须从文本文件中插入大约200万行.

插入时我必须创建一些主表.

将如此大量的数据插入SQL Server的最佳和快速方法是什么?

Pra*_*ana 66

  1. 我认为你在DataSet中读取文本文件的数据会更好

  2. 试用 SqlBulkCopy - 从C#App批量插入SQL

    // connect to SQL
    using (SqlConnection connection = new SqlConnection(connString))
    {
        // make sure to enable triggers
        // more on triggers in next post
        SqlBulkCopy bulkCopy = new SqlBulkCopy(
            connection, 
            SqlBulkCopyOptions.TableLock | 
            SqlBulkCopyOptions.FireTriggers | 
            SqlBulkCopyOptions.UseInternalTransaction,
            null
            );
    
        // set the destination table name
        bulkCopy.DestinationTableName = this.tableName;
        connection.Open();
    
        // write the data in the "dataTable"
        bulkCopy.WriteToServer(dataTable);
        connection.Close();
    }
    // reset
    this.dataTable.Clear();
    
    Run Code Online (Sandbox Code Playgroud)

要么

在顶部执行第1步之后

  1. 从DataSet创建XML
  2. 将XML传递给数据库并进行批量插入

您可以查看本文的详细信息:使用C#DataTable和SQL Server OpenXML函数批量插入数据

但它没有测试200万条记录,它会消耗内存,因为你必须加载200万条记录并插入它.

  • 您可以设置缓冲区以避免内存不足异常.对于文本文件,我使用了File.ReadLines(文件).Skip(X).Take(100000).ToList().每100k后我重置并移动到下一个100k.工作得很好而且很快. (16认同)

Son*_*nül 54

你可以尝试SqlBulkCopy上课.

允许您使用来自其他源的数据有效地批量加载SQL Server表.

一篇关于如何使用它的很酷的博客文章.


Ami*_*mir 24

重新解决SqlBulkCopy的问题:

我使用StreamReader来转换和处理文本文件.结果是我的对象列表.

我创建了一个类而不是take Datatable或a List<T>和Buffer size(CommitBatchSize).它将使用扩展名(在第二个类中)将列表转换为数据表.

它工作得非常快.在我的电脑上,我可以在不到10秒的时间内插入超过1000万条复杂的记录.

这是班级:

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

namespace DAL
{

public class BulkUploadToSql<T>
{
    public IList<T> InternalStore { get; set; }
    public string TableName { get; set; }
    public int CommitBatchSize { get; set; }=1000;
    public string ConnectionString { get; set; }

    public void Commit()
    {
        if (InternalStore.Count>0)
        {
            DataTable dt;
            int numberOfPages = (InternalStore.Count / CommitBatchSize)  + (InternalStore.Count % CommitBatchSize == 0 ? 0 : 1);
            for (int pageIndex = 0; pageIndex < numberOfPages; pageIndex++)
                {
                    dt= InternalStore.Skip(pageIndex * CommitBatchSize).Take(CommitBatchSize).ToDataTable();
                BulkInsert(dt);
                }
        } 
    }

    public void BulkInsert(DataTable dt)
    {
        using (SqlConnection connection = new SqlConnection(ConnectionString))
        {
            // make sure to enable triggers
            // more on triggers in next post
            SqlBulkCopy bulkCopy =
                new SqlBulkCopy
                (
                connection,
                SqlBulkCopyOptions.TableLock |
                SqlBulkCopyOptions.FireTriggers |
                SqlBulkCopyOptions.UseInternalTransaction,
                null
                );

            // set the destination table name
            bulkCopy.DestinationTableName = TableName;
            connection.Open();

            // write the data in the "dataTable"
            bulkCopy.WriteToServer(dt);
            connection.Close();
        }
        // reset
        //this.dataTable.Clear();
    }

}

public static class BulkUploadToSqlHelper
{
    public static DataTable ToDataTable<T>(this IEnumerable<T> data)
    {
        PropertyDescriptorCollection properties =
            TypeDescriptor.GetProperties(typeof(T));
        DataTable table = new DataTable();
        foreach (PropertyDescriptor prop in properties)
            table.Columns.Add(prop.Name, Nullable.GetUnderlyingType(prop.PropertyType) ?? prop.PropertyType);
        foreach (T item in data)
        {
            DataRow row = table.NewRow();
            foreach (PropertyDescriptor prop in properties)
                row[prop.Name] = prop.GetValue(item) ?? DBNull.Value;
            table.Rows.Add(row);
        }
        return table;
    }
}
Run Code Online (Sandbox Code Playgroud)

}

这是当我想插入我的自定义对象的列表的示例List<PuckDetection>(ListDetections):

var objBulk = new BulkUploadToSql<PuckDetection>()
{
        InternalStore = ListDetections,
        TableName= "PuckDetections",
        CommitBatchSize=1000,
        ConnectionString="ENTER YOU CONNECTION STRING"
};
objBulk.Commit();
Run Code Online (Sandbox Code Playgroud)

BulkInsert类可以修改,如果需要添加的列映射.将Identity密钥作为第一列的示例.(假设数据表中的列名与数据库相同)

//ADD COLUMN MAPPING
foreach (DataColumn col in dt.Columns)
{
        bulkCopy.ColumnMappings.Add(col.ColumnName, col.ColumnName);
}
Run Code Online (Sandbox Code Playgroud)


小智 6

我使用 bcp 实用程序。(批量复制程序)我每个月加载大约 150 万条文本记录。每个文本记录的宽度为 800 个字符。在我的服务器上,将 150 万条文本记录添加到 SQL Server 表中大约需要 30 秒。

bcp 的说明位于http://msdn.microsoft.com/en-us/library/ms162802.aspx