MSSQLデータベースのユーザー定義テーブルタイプを使用して、挿入の最適化を行い、2秒で10wのデータを挿入します

元のテキストは
次のとおりです。https://www.cnblogs.com/knowledgesea/p/6232461.html

より高速な挿入方法は2つあります。1つ
は2秒で10wを挿入するカスタムテーブルタイプで、
2つ目の一般的なBULKINSERTデータセットは1秒で10wを挿入するように最適化されています。

カスタムテーブルタイプの最適化方法を見てみましょう
。SQLServer2012以降、10wのデータを2秒未満で挿入できます。

まず、データベースに新しいタイプを作成します。

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 + "毫秒。");
                }
            }
        }

まず、int、varchar、bitなどがすべての型であるなど、誰もが理解しやすい型である必要があります。次に、このテーブル型は糸ですか?

実際、これは、ユーザーが自分でテーブル構造を定義し、それを型として扱うことができることを意味します。

カスタムタイプを作成するための詳細なドキュメント:https://msdn.microsoft.com/zh-cn/library/ms175007.aspx

次に、カスタムタイプにもいくつかの制限、セキュリティがあります:https://msdn.microsoft.com/zh-cn/library/bb522526.aspx

次に、このタイプの使用方法を説明します。彼の使用は、テーブル値パラメーターとして使用されます。

テーブル値パラメーターを使用すると、一時テーブルや多くのパラメーターを作成せずに、複数行のデータをTransact-SQLステートメントまたはルーチン(ストアドプロシージャや関数など)に送信できます。

テーブル値パラメーターは、OLE DBおよびODBCのパラメーター配列に似ていますが、柔軟性が高く、Transact-SQLとより緊密に統合されています。テーブル値パラメーターのもう1つの利点は、データセットに基づく操作に参加できることです。

Transact-SQLは、入力データのコピーの作成を回避するために、参照によってテーブル値パラメーターをルーチンに渡します。テーブル値パラメーターを使用してTransact-SQLルーチンを作成および実行でき、任意のマネージ言語を使用して、Transact-SQLコード、マネージクライアント、およびネイティブクライアントからそれらを呼び出すことができます。

利点

他のパラメーターと同様に、テーブル値パラメーターのスコープも、ストアドプロシージャ、関数、または動的なTransact-SQLテキストです。同様に、テーブルタイプ変数は、DECLAREステートメントを使用して作成された他のローカル変数と同じスコープを持ちます。動的なTransact-SQLステートメント内でテーブル値変数を宣言でき、これらの変数をテーブル値パラメーターとしてストアドプロシージャおよび関数に渡すことができます。

テーブル値パラメーターは柔軟性が高く、場合によっては、一時テーブルやパラメーターリストを渡す他の方法よりも優れたパフォーマンスを提供できます。テーブル値パラメーターには、次の利点があります。

クライアントからのデータを初めて入力するとき、ロックは取得されません。

簡単なプログラミングモデルを提供します。

複雑なビジネスロジックを単一のルーチンに含めることができます。

サーバーへのラウンドトリップを減らします。

カーディナリティが異なるテーブル構造を持つことができます。

強く型付けされています。

クライアントがソート順と一意のキーを指定できるようにします。

ストアドプロシージャで使用すると、一時テーブルのようにキャッシュされます。SQL Server 2012以降、パラメーター化されたクエリの場合、テーブル値のパラメーターもキャッシュされます。

制限

テーブル値パラメーターには、以下の制限があります。

SQL Serverは、テーブル値のパラメーター列の統計を維持しません。

テーブル値パラメーターは、入力READONLYパラメーターとしてTransact-SQLルーチンに渡す必要があります。ルーチン本体のテーブル値パラメーターに対して、UPDATE、DELETE、INSERTなどのDML操作を実行することはできません。

表値パラメーターをSELECTINTOまたはINSERTEXECステートメントのターゲットとして使用することはできません。テーブル値パラメーターは、SELECT INTOのFROM句、またはINSERTEXEC文字列またはストアドプロシージャに含めることができます。

一般的なBULKINSERTデータセット挿入の最適化

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 + "毫秒。");
            }

おすすめ

転載: blog.csdn.net/phker/article/details/103124792