中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

SQLServer批量插入數據的方式有哪些

發布時間:2021-12-20 09:05:24 來源:億速云 閱讀:422 作者:iii 欄目:開發技術

本篇內容主要講解“SQLServer批量插入數據的方式有哪些”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“SQLServer批量插入數據的方式有哪些”吧!

技術方案一:

壓縮時間下程序員寫出的第一個版本,僅僅為了完成任務,沒有從程序上做任何優化,實現方式是利用數據庫訪問類調用存儲過程,利用循環逐條插入。很明顯,這種方式效率并不高,于是有了前面的兩位同事討論效率低的問題。

技術方案二:

由于是考慮到大數據量的批量插入,于是我想到了ADO.NET2.0的一個新的特性:SqlBulkCopy。有關這個的性能,很早之前我是親自做過性能測試的,效率非常高。這也是我向公司同事推薦的技術方案。

技術方案三:

利用SQLServer2008的新特性--表值參數(Table-Valued Parameter)。表值參數是SQLServer2008才有的一個新特性,使用這個新特性,我們可以把一個表類型作為參數傳遞到函數或存儲過程里。不過,它也有一個特點:表值參數在插入數目少于 1000 的行時具有很好的執行性能。

技術方案四:

對于單列字段,可以把要插入的數據進行字符串拼接,最后再在存儲過程中拆分成數組,然后逐條插入。查了一下存儲過程中參數的字符串的最大長度,然后除以字段的長度,算出一個值,很明顯是可以滿足要求的,只是這種方式跟第一種方式比起來,似乎沒什么提高,因為原理都是一樣的。

技術方案五:

考慮異步創建、消息隊列等等。這種方案無論從設計上還是開發上,難度都是有的。

技術方案一肯定是要被否掉的了,剩下的就是在技術方案二跟技術方案三之間做一個抉擇,鑒于公司目前的情況,技術方案四跟技術方案五就先不考慮了。

接下來,為了讓大家對表值參數的創建跟調用有更感性的認識,我將寫的更詳細些,文章可能也會稍長些,不關注細節的朋友們可以選擇跳躍式的閱讀方式。

再說一下測試方案吧,測試總共分三組,一組是插入數量小于1000的,另外兩組是插入數據量大于1000的(這里我們分別取10000跟1000000),每組測試又分10次,取平均值。怎么做都明白了,Let's go!

1.創建表。

為了簡單,表中只有一個字段,如下圖所示:

SQLServer批量插入數據的方式有哪些

2.創建表值參數類型

我們打開查詢分析器,然后在查詢分析器中執行下列代碼:

Create Type PassportTableType as Table
(
PassportKey nvarchar(50)

)

執行成功以后,我們打開企業管理器,按順序依次展開下列節點--數據庫、展開可編程性、類型、用戶自定義表類型,就可以看到我們創建好的表值類型了如下圖所示:

SQLServer批量插入數據的方式有哪些

說明我們創建表值類型成功了。

3.編寫存儲過程

存儲過程的代碼為:

USE [TestInsert]

GO
/****** Object: StoredProcedure [dbo].[CreatePassportWithTVP] Script Date: 03/02/2010 00:14:45 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- =============================================
-- Author:	<Kevin>
-- Create date: <2010-3-1>
-- Description:	<創建通行證>
-- =============================================
Create PROCEDURE [dbo].[CreatePassportWithTVP] 

@TVP PassportTableType readonly

AS
BEGIN
SET NOCOUNT ON;

Insert into Passport(PassportKey) select PassportKey from @TVP

END

可能在查詢分析器中,智能提示會提示表值類型有問題,會出現紅色下劃線(見下圖),不用理會,繼續運行我們的代碼,完成存儲過程的創建

SQLServer批量插入數據的方式有哪些

4.編寫代碼調用存儲過程。

三種數據庫的插入方式代碼如下,由于時間比較緊,代碼可能不那么易讀,特別代碼我加了些注釋。

using System;
using System.Diagnostics;
using System.Data;
using System.Data.SqlClient;
using com.DataAccess;

namespace ConsoleAppInsertTest
{
    class Program
    {
        static string connectionString = SqlHelper.ConnectionStringLocalTransaction;    //數據庫連接字符串
        static int count = 1000000;           //插入的條數
        static void Main(string[] args)
        {
            //long commonInsertRunTime = CommonInsert();
            //Console.WriteLine(string.Format("普通方式插入{1}條數據所用的時間是{0}毫秒", commonInsertRunTime, count));

            long sqlBulkCopyInsertRunTime = SqlBulkCopyInsert();
            Console.WriteLine(string.Format("使用SqlBulkCopy插入{1}條數據所用的時間是{0}毫秒", sqlBulkCopyInsertRunTime, count));

            long TVPInsertRunTime = TVPInsert();
            Console.WriteLine(string.Format("使用表值方式(TVP)插入{1}條數據所用的時間是{0}毫秒", TVPInsertRunTime, count));
        }

        /// <summary>
        /// 普通調用存儲過程插入數據
        /// </summary>
        /// <returns></returns>
        private static long CommonInsert()
        {
            Stopwatch stopwatch = new Stopwatch();
            stopwatch.Start();
            
            string passportKey;
            for (int i = 0; i < count; i++)
            {
                passportKey = Guid.NewGuid().ToString();
                SqlParameter[] sqlParameter = { new SqlParameter("@passport", passportKey) };
                SqlHelper.ExecuteNonQuery(connectionString, CommandType.StoredProcedure, "CreatePassport", sqlParameter);
            }
            stopwatch.Stop();
            return stopwatch.ElapsedMilliseconds;
        }

        /// <summary>
        /// 使用SqlBulkCopy方式插入數據
        /// </summary>
        /// <param name="dataTable"></param>
        /// <returns></returns>
        private static long SqlBulkCopyInsert()
        {
            Stopwatch stopwatch = new Stopwatch();
            stopwatch.Start();

            DataTable dataTable = GetTableSchema();
            string passportKey;
            for (int i = 0; i < count; i++)
            {
                passportKey = Guid.NewGuid().ToString();
                DataRow dataRow = dataTable.NewRow();
                dataRow[0] = passportKey;
                dataTable.Rows.Add(dataRow);
            }

            SqlBulkCopy sqlBulkCopy = new SqlBulkCopy(connectionString);
            sqlBulkCopy.DestinationTableName = "Passport";
            sqlBulkCopy.BatchSize = dataTable.Rows.Count;
            SqlConnection sqlConnection = new SqlConnection(connectionString);
            sqlConnection.Open();
            if (dataTable!=null && dataTable.Rows.Count!=0)
            {
                sqlBulkCopy.WriteToServer(dataTable);
            }
            sqlBulkCopy.Close();
            sqlConnection.Close();

            stopwatch.Stop();
            return stopwatch.ElapsedMilliseconds;
        }

        private static long TVPInsert()
        {
            Stopwatch stopwatch = new Stopwatch();
            stopwatch.Start();

            DataTable dataTable = GetTableSchema();
            string passportKey;
            for (int i = 0; i < count; i++)
            {
                passportKey = Guid.NewGuid().ToString();
                DataRow dataRow = dataTable.NewRow();
                dataRow[0] = passportKey;
                dataTable.Rows.Add(dataRow);
            }

            SqlParameter[] sqlParameter = { new SqlParameter("@TVP", dataTable) };
            SqlHelper.ExecuteNonQuery(connectionString, CommandType.StoredProcedure, "CreatePassportWithTVP", sqlParameter);

            stopwatch.Stop();
            return stopwatch.ElapsedMilliseconds;
        }

        private static DataTable GetTableSchema()
        {
            DataTable dataTable = new DataTable();
            dataTable.Columns.AddRange(new DataColumn[] { new DataColumn("PassportKey") });
            
            return dataTable;
        }

    }
}

比較神秘的代碼其實就下面這兩行,該代碼是將一個dataTable做為參數傳給了我們的存儲過程。簡單吧。

SqlParameter[] sqlParameter = { new SqlParameter("@TVP", dataTable) };

SqlHelper.ExecuteNonQuery(connectionString, CommandType.StoredProcedure, "CreatePassportWithTVP", sqlParameter);

5.測試并記錄測試結果

第一組測試,插入記錄數1000

SQLServer批量插入數據的方式有哪些

第二組測試,插入記錄數10000

SQLServer批量插入數據的方式有哪些

第三組測試,插入記錄數1000000

SQLServer批量插入數據的方式有哪些

通過以上測試方案,不難發現,技術方案二的優勢還是蠻高的。無論是從通用性還是從性能上考慮,都應該是優先被選擇的,還有一點,它的技術復雜度要比技術方案三要簡單一些,設想我們把所有表都創建一遍表值類型,工作量還是有的。因此,我依然堅持我開始時的決定,向公司推薦使用第二種技術方案。

到此,相信大家對“SQLServer批量插入數據的方式有哪些”有了更深的了解,不妨來實際操作一番吧!這里是億速云網站,更多相關內容可以進入相關頻道進行查詢,關注我們,繼續學習!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

余庆县| 广西| 资溪县| 新郑市| 吐鲁番市| 佛坪县| 特克斯县| 华阴市| 云林县| 区。| 师宗县| 龙山县| 虞城县| 霍林郭勒市| 云林县| 莱州市| 大厂| 南昌县| 尼勒克县| 平远县| 陇南市| 将乐县| 丹凤县| 临漳县| 成武县| 宜兰市| 顺平县| 冀州市| 合川市| 罗山县| 连平县| 光泽县| 南汇区| 临西县| 榆中县| 辛集市| 六盘水市| 开远市| 浦城县| 福清市| 台南县|