Use the user-defined table type of MSSQL database to do insert optimization, insert 10w data in 2 seconds

The original text comes
from.https://www.cnblogs.com/knowledgesea/p/6232461.html

There are two faster insertion methods. The
first is a custom table type that inserts 10w in 2 seconds, and the
second common BULK INSERT data set is optimized to insert 10w in 1 second.

Let's take a look at the optimization method of the custom table type.
After SQL Server 2012, 10w pieces of data can be inserted in less than 2 seconds.

First create a new type in the database.

CREATE TYPE CustomerFeedbackTemp AS  TABLE(
BusType int NOT NULL,
CustomerPhone varchar(40) NOT NULL,
BackType int NOT NULL,
Content nvarchar(1000) NOT NULL
)
public void ThirdWay()
        {
    
    
            Stopwatch sw = new Stopwatch();
            Stopwatch sw1 = new Stopwatch();
            DataTable dt = GetTable();
            using (var conn = new SqlConnection(ConnStr))
            {
    
    
                string sql = @"INSERT INTO[dbo].[CustomerFeedback]
                                           ([BusType]
                                           ,[CustomerPhone]
                                           ,[BackType]
                                           ,[Content]
                                          ) select BusType,CustomerPhone,BackType,[Content] from @TempTb";
                using (SqlCommand cmd = new SqlCommand(sql, conn))
                {
    
    
                    cmd.CommandTimeout = 0;
                    SqlParameter catParam = cmd.Parameters.AddWithValue("@TempTb", dt);
                    catParam.SqlDbType = SqlDbType.Structured;
                    catParam.TypeName = "dbo.CustomerFeedbackTemp";
                    conn.Open();
                    Console.WriteLine("从:" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss fff") + "开始循环插入内存表中:" + cnt + "条数据 ...");
                    sw.Start();
                    for (int i = 0; i < cnt; i++)
                    {
    
    
                        DataRow dr = dt.NewRow();
                        dr[0] = m.BusType;
                        dr[1] = m.CustomerPhone;
                        dr[2] = m.BackType;
                        dr[3] = m.Content;
                        dt.Rows.Add(dr);
                    }
                    Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss fff") + "时,循环插入内存表:" + cnt + "条数据完成 ! 耗时:" + sw.ElapsedMilliseconds + "毫秒。");
                    sw1.Start();
                    if (dt != null && dt.Rows.Count != 0)
                    {
    
    
                        cmd.ExecuteNonQuery();
                        sw.Stop();
                    }
                    Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss fff") + "时,执行:" + cnt + "条数据的datatable的数据进数据库 ! 耗时:" + sw1.ElapsedMilliseconds + "毫秒。");
                }
            }
        }

First of all, the type should be easy for everyone to understand, like int, varchar, bit, etc. are all types, then this table type is a yarn?

In fact, it means that users can define a table structure by themselves and treat him as a type.

Detailed documentation for creating custom types: https://msdn.microsoft.com/zh-cn/library/ms175007.aspx

Secondly, custom types also have some restrictions, security: https://msdn.microsoft.com/zh-cn/library/bb522526.aspx

Then is how to use this type, his use is used as a table-valued parameter.

Using table-valued parameters, you can send multiple rows of data to Transact-SQL statements or routines (such as stored procedures or functions) without creating temporary tables or many parameters.

Table-valued parameters are similar to the parameter arrays in OLE DB and ODBC, but have higher flexibility and are more tightly integrated with Transact-SQL. Another advantage of table-valued parameters is the ability to participate in operations based on data sets.

Transact-SQL passes table-valued parameters to the routine by reference to avoid creating a copy of the input data. You can use table-valued parameters to create and execute Transact-SQL routines, and you can use any managed language to call them from Transact-SQL code, managed clients, and native clients.

advantage

Just like other parameters, the scope of table-valued parameters is also a stored procedure, function, or dynamic Transact-SQL text. Similarly, table type variables have the same scope as any other local variables created using the DECLARE statement. You can declare table-valued variables within dynamic Transact-SQL statements, and you can pass these variables as table-valued parameters to stored procedures and functions.

Table-valued parameters have higher flexibility. In some cases, they can provide better performance than temporary tables or other methods of passing parameter lists. Table-valued parameters have the following advantages:

When filling data from the client for the first time, no lock is acquired.

Provide a simple programming model.

Allow complex business logic to be included in a single routine.

Reduce round trips to the server.

Can have table structures with different cardinality.

It is strongly typed.

Enable the client to specify the sort order and unique key.

When used in a stored procedure, it is cached like a temporary table. Starting from SQL Server 2012, for parameterized queries, table-valued parameters are also cached.

limit

Table-valued parameters have the following restrictions:

SQL Server does not maintain statistics for table-valued parameter columns.

Table-valued parameters must be passed to Transact-SQL routines as input READONLY parameters. You cannot perform DML operations such as UPDATE, DELETE, or INSERT on table-valued parameters in the routine body.

You cannot use table-valued parameters as the target of a SELECT INTO or INSERT EXEC statement. Table-valued parameters can be in the FROM clause of SELECT INTO, or in INSERT EXEC strings or stored procedures.

Common BULK INSERT data set insertion optimization

public void FourWay()
        {
    
    

            Stopwatch sw = new Stopwatch();
            Stopwatch sw1 = new Stopwatch();
            DataTable dt = GetTable();
            using (SqlConnection conn = new SqlConnection(ConnStr))
            {
    
    
                SqlBulkCopy bulkCopy = new SqlBulkCopy(conn);
                bulkCopy.BulkCopyTimeout = 0;
                bulkCopy.DestinationTableName = "CustomerFeedback";
                bulkCopy.BatchSize = dt.Rows.Count;
                conn.Open();
                Console.WriteLine("从:" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss fff") + "开始循环插入内存表中:" + cnt + "条数据 ...");
                sw.Start();
                for (int i = 0; i < cnt; i++)
                {
    
    
                    DataRow dr = dt.NewRow();
                    dr[0] = m.BusType;
                    dr[1] = m.CustomerPhone;
                    dr[2] = m.BackType;
                    dr[3] = m.Content;
                    dt.Rows.Add(dr);
                }
                Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss fff") + "时,循环插入内存表:" + cnt + "条数据完成 ! 耗时:" + sw.ElapsedMilliseconds + "毫秒。");
                sw1.Start();
                if (dt != null && dt.Rows.Count != 0)
                {
    
    
                    bulkCopy.WriteToServer(dt);
                    sw.Stop();
                }
                Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss fff") + "时,执行:" + cnt + "条数据的datatable的数据进数据库 ! 耗时:" + sw1.ElapsedMilliseconds + "毫秒。");
            }

Guess you like

Origin blog.csdn.net/phker/article/details/103124792