1. ホーム
  2. データベース
  3. エムエスエル

SQL Server一括挿入データ事例詳細

2022-01-18 11:38:16

SQL Serverでデータを挿入するにはInsert文を使用しますが、大量のデータを一括して挿入する場合、Insertを周期的に使用すると効率が悪いだけでなく、SQL aシステムのパフォーマンス問題の原因となります。ここでは、SQL Serverがサポートする2つの一括データ挿入方法を紹介します。一括挿入とTVP(Table-Valued Parameters)を使って、効率的にデータを挿入します。

データベースを新規に作成するには

--Create DataBase  
create database BulkTestDB;  
go  
use BulkTestDB;  
go  
--Create Table  
Create table BulkTestTable(  
Id int primary key,  
UserName nvarchar(32),  
Pwd varchar(16))  
go 

I. 従来のINSERTアプローチ

まず、従来のINSERTアプローチを見てみましょう。1つずつ挿入していきます(パフォーマンス消費と速度低下が増加します)。

        //Insert one by one using the simpleInsert method [slow]
        #region [ simpleInsert ]
        static void simpleInsert()
        {
            Console.WriteLine("Insert one bar at a time using the simpleInsert method");
            Stopwatch sw = new Stopwatch();
            SqlConnection sqlconn = new SqlConnection("server=. ;database=BulkTestDB;user=sa;password=123456;");
            SqlCommand sqlcmd = new SqlCommand();
            sqlcmd.CommandText = string.Format("insert into BulkTestTable(Id,UserName,Pwd)values(@p0,@p1,@p2)");
            sqlcmd.Parameters.Add("@p0", SqlDbType.Int);
            sqlcmd.Parameters.Add("@p1", SqlDbType.NVarChar);
            sqlcmd.Parameters.Add("@p2", SqlDbType.NVarChar);
            sqlcmd.CommandType = CommandType.Text;
            sqlcmd.Connection = sqlconn;
            Open();
            Open(); try
            {
                //Insert 1000 pieces of data in a loop, 100 pieces at a time, 10 times.  
                for (int multiply = 0; multiply < 10; multiply++)
                {
                    for (int count = multiply * 100; count < (multiply + 1) * 100; count++)
                    {
 
                        sqlcmd.Parameters["@p0"].Value = count;
                        sqlcmd.Parameters["@p1"].Value = string.Format("User-{0}", count * multiply);
                        sqlcmd.Parameters["@p2"].Value = string.Format("Pwd-{0}", count * multiply);
                        sw.Start();
                        sqlcmd.ExecuteNonQuery();
                        sw.Stop();
                    }
                    // After every 100,000 data insertions, display the time spent on this insertion  
                    Console.WriteLine(string.Format("Elapsed Time is {0} Milliseconds", sw.ElapsedMilliseconds));
                }
                Console.ReadKey();
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
        }
        #endregion

1000件のデータ挿入を100件ずつ10回ループさせると、効率がどんどん悪くなっていきます。

II. より迅速なバルク挿入方法。

一括挿入を利用することで、[ より速く ]。

        //Insertion with Bulk [ faster]
        #region [ inserted using Bulk]
        static void BulkToDB(DataTable dt)
        {
            Stopwatch sw = new Stopwatch();
            SqlConnection sqlconn = new SqlConnection("server=. ;database=BulkTestDB;user=sa;password=123456;");
            SqlBulkCopy bulkCopy = new SqlBulkCopy(sqlconn);
            bulkCopy.DestinationTableName = "BulkTestTable";
            BatchSize = dt.Rows;
            BatchSize = dt.
            {
                sqlconn.Open();
                if (dt ! = null && dt.Rows.Count ! = 0)
                {
                    bulkCopy.WriteToServer(dt);
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
            finally
            {
                sqlconn.Close();
                if (bulkCopy ! = null)
                {
                    bulkCopy.Close();
                }
            }
        }
        static DataTable GetTableSchema()
        {
            DataTable dt = new DataTable();
            dt.Columns.AddRange(new DataColumn[] { 
                new DataColumn("Id",typeof(int)),
                new DataColumn("UserName",typeof(string)),
                new DataColumn("Pwd",typeof(string))
            });
            return dt;
        }
        static void BulkInsert()
        {
            Console.WriteLine("The case of using a simple Bulk insert");
            Stopwatch sw = new Stopwatch();
            for (int multiply = 0; multiply < 10; multiply++)
            {
                DataTable dt = GetTableSchema();
                for (int count = multiply * 100; count < (multiply + 1) * 100; count++)
                {
                    DataRow r = dt.NewRow();
                    r[0] = count;
                    r[1] = string.Format("User-{0}", count * multiply);
                    r[2] = string.Format("Pwd-{0}", count * multiply);
                    dt.Rows.Add(r);
                }
                sw.Start();
                BulkToDB(dt);
                sw.Stop();
                Console.WriteLine(string.Format("Elapsed Time is {0} Milliseconds", sw.ElapsedMilliseInsert 1000 pieces of data cyclically, 100 pieces each time, 10 times, much faster efficiency.

III. Inserting data using the abbreviation TVPs

Open sqlserrver and execute the following script.

--Create Table Valued  
CREATE TYPE BulkUdt AS TABLE  
  (Id int,  
   UserName nvarchar(32),  
   Pwd varchar(16))  

After success, we found more cache tables for BulkUdt in the database.

Insert data using the abbreviation TVPs

        //Insert data using abbreviated TVPs [fastest]
        #region [ insert data using abbreviated TVPs ]
        static void TbaleValuedToDB(DataTable dt)
        {
            Stopwatch sw = new Stopwatch();
            SqlConnection sqlconn = new SqlConnection("server=. ;database=BulkTestDB;user=sa;password=123456;");
            const string TSqlStatement =
                  "insert into BulkTestTable (Id,UserName,Pwd)" +
                  " SELECT nc.Id, nc.UserName,nc.Pwd" +
                  " FROM @NewBulkTestTvp AS nc";
            SqlCommand cmd = new SqlCommand(TSqlStatement, sqlconn);
            SqlParameter catParam = cmd.Parameters.AddWithValue("@NewBulkTestTvp", dt);
            catParam.SqlDbType = SqlDbType.Structured;
            catParam.TypeName = "dbo.BulkUdt";
            try
            {
                sqlconn.Open();
                if (dt ! = null && dt.Rows.Count ! = 0)
                {
                    cmd.ExecuteNonQuery();
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine("error>" + ex.Message);
            }
            finally
            {
                sqlconn.Close();
            }
        }
        static void TVPsInsert()
        {
            Console.WriteLine("Inserting data using the abbreviation TVPs");
            Stopwatch sw = new Stopwatch();
            for (int multiply = 0; multiply < 10; multiply++)
            {
                DataTable dt = GetTableSchema();
                for (int count = multiply * 100; count < (multiply + 1) * 100; count++)
                {
                    DataRow r = dt.NewRow();
                    r[0] = count;
                    r[1] = string.Format("User-{0}", count * multiply);
                    r[2] = string.Format("Pwd-{0}", count * multiply);
                    dt.Rows.Add(r);
                }
                sw.Start();
                TbaleValuedToDB(dt);
                sw.Stop();
                Console.WriteLine(string.Format("Elapsed Time is {0} Milliseconds", sw.ElapsedMilliseconds));
            }
            Console.ReadLine();  
        }
        #endregion

The efficiency is getting slower and slower when inserting 1000 pieces of data cyclically, 100 pieces each time, 10 times. Later test, increase the amount of data inserted each time, it will reflect the efficiency of TPVS insertion more.

This article about SQL Server batch insert data case is introduced to this, more related SQL Server batch insert data content please search the previous articles of the Codedevlib or continue to browse the following related articles hope you will support the Codedevlib more in the future!