zoukankan      html  css  js  c++  java
  • SqlBulkCopy快速批量大数据插入

    测试数据表
    CREATE TABLE [dbo].[Demo](
        [ID] [int] IDENTITY(1,1) NOT NULL,
        [Time] [datetime] NULL,
        [Name] [nvarchar](50) NULL,
        [Has] [bit] NULL,
        [Age] [int] NULL
    ) ON [PRIMARY]
    .Net批量插入
    private void batchInsert()
    {
                DataTable dt = new DataTable("demo");
                dt.Columns.Add("ID", typeof(System.Int32)); //虽然ID为自增字段,但仍然要添加列,否则会报异常“来自数据源的 String 类型的给定值不能转换为指定目标列的类型 datetime。”
                dt.Columns.Add("Time", typeof(System.DateTime));
                dt.Columns.Add("Name", typeof(System.String));
                dt.Columns.Add("Has", typeof(System.Int32));
                dt.Columns.Add("Age", typeof(System.Int32));
    
                for (int i = 0; i < 100000; i++)
                {
                    DataRow dr = dt.NewRow();
                    dr["Time"] = DateTime.Now;
                    dr["Name"] = "Demo";
                    dr["Has"] = 1;
                    dr["Age"] = 10;
                    dt.Rows.Add(dr);
                }
                AddDataTable(dt);
    }
    
    public bool AddDataTable(DataTable dt)
    {
                using (SqlConnection conn = new SqlConnection(sqlHelper.SQLConString))
                {
                    SqlTransaction transaction = null;
                    try
                    {
                        conn.Open();
                        transaction = conn.BeginTransaction();
                        SqlBulkCopy sbc = new SqlBulkCopy(conn, SqlBulkCopyOptions.CheckConstraints, transaction);
                        sbc.DestinationTableName = dt.TableName;
                        sbc.BatchSize = dt.Rows.Count;
                        sbc.BulkCopyTimeout = 180;
                        sbc.WriteToServer(dt);
                        transaction.Commit();
                        return true;
                    }
                    catch (Exception ex)
                    {
                        LogMsg.WriteLog(ex.ToString());
                        transaction.Rollback();
                    }
                }
    
                return false;
    }
    VB.Net批量插入
    Protected SQLConString As String = ConfigurationManager.ConnectionStrings("connectionstring").ToString()
        Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
            Dim startDate As DateTime = DateTime.Now
            'batchInsert()  '1198.6272毫秒
            OneInsert()  '604554.6833毫秒
            Dim endDate As DateTime = DateTime.Now
            Response.Write((endDate - startDate).TotalMilliseconds)
    
    End Sub
    
    '单条数据添加
    Private Sub OneInsert()
            Using conn As New SqlClient.SqlConnection(SQLConString)
                Try
                    conn.Open()
                    Dim cmd As New SqlClient.SqlCommand
                    cmd.Connection = conn
                    cmd.CommandType = CommandType.Text
                    For index = 1 To 100000
                        cmd.CommandText = "insert demo(Time,Name,Has,Age)values('" & DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") & "','第一个',1,18)"
                        cmd.ExecuteNonQuery()
                    Next
                Catch ex As Exception
    
                End Try
            End Using
    End Sub
    
    '一次性批量添加
    Private Sub batchInsert()
            Dim dt As New DataTable("demo")
            dt.Columns.Add("ID", GetType(Integer)) '虽然ID为自增字段,但仍然要添加列,否则会报异常“来自数据源的 String 类型的给定值不能转换为指定目标列的类型 datetime。”
            dt.Columns.Add("Time", GetType(DateTime))
            dt.Columns.Add("Name", GetType(String))
            dt.Columns.Add("Has", GetType(Integer))
            dt.Columns.Add("Age", GetType(Integer))
    
    
            For i = 1 To 100000
                Dim row As DataRow = dt.NewRow()
                row("Time") = DateTime.Now
                row("Name") = "第一个"
                row("Has") = 1
                row("Age") = 18
                dt.Rows.Add(row)
            Next
    
            Using conn As New SqlClient.SqlConnection(SQLConString)
                Dim transaction As SqlClient.SqlTransaction
                Try
                    conn.Open()
                    transaction = conn.BeginTransaction()
                    Dim sbc As New SqlClient.SqlBulkCopy(conn, SqlBulkCopyOptions.CheckConstraints, transaction)
                    sbc.DestinationTableName = dt.TableName
                    sbc.BatchSize = dt.Rows.Count
                    sbc.BulkCopyTimeout = 180
                    sbc.WriteToServer(dt)
                    transaction.Commit()
                Catch ex As Exception
                    transaction.Rollback()
                End Try
            End Using
    End Sub
    效率对比

    通过上面的VB.NET的两种添加方式对比,同样是一次性添加10w数据,以下是他们的执行时间:

    (时间单位:毫秒)

    SqlBulkCopy:1198.6272≈1秒

    for insert:604554.6833≈10分钟

    使用中遇到的小问题(Q&A)

    问题1:从bcp客户端收到一个对Colid 24 无效的列长度

    原因:第24列的参数长度大于数据库列定义长度。

    问题2:报异常“来自数据源的 String 类型的给定值不能转换为指定目标列的类型 datetime。”

    原因: 没有添加自增列。

  • 相关阅读:
    iOS开发App上传的三大步骤
    iOS开发关于AppStore程序的上传流程
    AFNetworking 3.0x版本最新特性
    iOS开发中两个不错的宏定义
    iOS开发中NSDate时间戳的转换--
    HDU 2844 Coins 多重背包
    poj 1888 Crossword Answers 模拟题
    杭电oj 1069 Monkey and Banana 最长递增子序列
    郑轻校赛题目 问题 G: 多少个0
    HDU 2571 命运
  • 原文地址:https://www.cnblogs.com/hougelou/p/2854655.html
Copyright © 2011-2022 走看看