zoukankan      html  css  js  c++  java
  • .NET批量大数据插入性能分析及比较

    数据插入使用了以下几种方式

    1. 逐条数据插入
    2. 拼接sql语句批量插入
    3. 拼接sql语句并使用Transaction
    4. 拼接sql语句并使用SqlTransaction
    5. 使用DataAdapter
    6. 使用TransactionScope及SqlBulkCopy
    7. 使用表值参数

    数据库使用SQL Server,脚本如下

    create table TestTable
    (
    Id int
    ,Name nvarchar(20)
    )

    程序中生成测试DataTable结构和测试数据的类如下

    [c-sharp] view plaincopyprint?
    1.public class Tools 
    2.{ 
    3.    public static DataTable MakeDataTable() 
    4.    { 
    5.        DataTable table = new DataTable(); 
    6. 
    7.        //生成DataTable的模式(schema)  
    8.        table.Columns.Add("Id", Type.GetType("System.Int32")); 
    9.        table.Columns.Add("Name", Type.GetType("System.String")); 
    10. 
    11.        //设置主键  
    12.        table.PrimaryKey = new DataColumn[] { table.Columns["ID"] }; 
    13.        table.Columns["Id"].AutoIncrement = true; 
    14.        table.Columns["Id"].AutoIncrementSeed = 1; 
    15.        table.Columns["Id"].ReadOnly = true; 
    16.        return table; 
    17.    } 
    18. 
    19.    public static void MakeData(DataTable table, int count) 
    20.    { 
    21.        if (table == null) 
    22.            return; 
    23. 
    24.        if (count <= 0) 
    25.            return; 
    26. 
    27.        DataRow row = null; 
    28. 
    29.        for (int i = 1; i <= count; i++) 
    30.        { 
    31.            //创建一个新的DataRow对象(生成一个新行)  
    32.            row = table.NewRow(); 
    33.            row["Name"] = "Test" + i.ToString(); 
    34.            //添加新的DataRow  
    35.            table.Rows.Add(row); 
    36.        } 
    37.    } 
    38.} 
        public class Tools
        {
            public static DataTable MakeDataTable()
            {
                DataTable table = new DataTable();

                //生成DataTable的模式(schema)
                table.Columns.Add("Id", Type.GetType("System.Int32"));
                table.Columns.Add("Name", Type.GetType("System.String"));

                //设置主键
                table.PrimaryKey = new DataColumn[] { table.Columns["ID"] };
                table.Columns["Id"].AutoIncrement = true;
                table.Columns["Id"].AutoIncrementSeed = 1;
                table.Columns["Id"].ReadOnly = true;
                return table;
            }

            public static void MakeData(DataTable table, int count)
            {
                if (table == null)
                    return;

                if (count <= 0)
                    return;

                DataRow row = null;

                for (int i = 1; i <= count; i++)
                {
                    //创建一个新的DataRow对象(生成一个新行)
                    row = table.NewRow();
                    row["Name"] = "Test" + i.ToString();
                    //添加新的DataRow
                    table.Rows.Add(row);
                }
            }
        }

    使用Log4net记录日志,默认插入记录数为40000条,每次插入1条,可在界面修改,使用System.Diagnostics.StopWatch记录插入时间,每次测试后删除原表重建

    窗体代码如下:

     

    1. public delegate bool InsertHandler(DataTable table, int batchSize);  
    2.   
    3. public partial class FrmBatch : Form  
    4. {  
    5.     private Stopwatch _watch = new Stopwatch();  
    6.   
    7.     public FrmBatch()  
    8.     {  
    9.         InitializeComponent();  
    10.     }  
    11.   
    12.     private void FrmBatch_Load(object sender, EventArgs e)  
    13.     {  
    14.         txtRecordCount.Text = "40000";  
    15.         txtBatchSize.Text = "1";  
    16.     }  
    17.   
    18.     //逐条数据插入   
    19.     private void btnInsert_Click(object sender, EventArgs e)  
    20.     {  
    21.         Insert(DbOperation.ExecuteInsert, "Use SqlServer Insert");  
    22.     }  
    23.   
    24.     //拼接sql语句插入   
    25.     private void btnBatchInsert_Click(object sender, EventArgs e)  
    26.     {  
    27.         Insert(DbOperation.ExecuteBatchInsert, "Use SqlServer Batch Insert");  
    28.     }  
    29.   
    30.     //拼接sql语句并使用Transaction   
    31.     private void btnTransactionInsert_Click(object sender, EventArgs e)  
    32.     {  
    33.         Insert(DbOperation.ExecuteTransactionInsert, "Use SqlServer Batch Transaction Insert");  
    34.     }  
    35.   
    36.     //拼接sql语句并使用SqlTransaction   
    37.     private void btnSqlTransactionInsert_Click(object sender, EventArgs e)  
    38.     {  
    39.         Insert(DbOperation.ExecuteSqlTransactionInsert, "Use SqlServer Batch SqlTransaction Insert");  
    40.     }  
    41.   
    42.     //使用DataAdapter   
    43.     private void btnDataAdapterInsert_Click(object sender, EventArgs e)  
    44.     {  
    45.         Insert(DbOperation.ExecuteDataAdapterInsert, "Use SqlServer DataAdapter Insert");  
    46.     }  
    47.   
    48.     //使用TransactionScope   
    49.     private void btnTransactionScopeInsert_Click(object sender, EventArgs e)  
    50.     {  
    51.         Insert(DbOperation.ExecuteTransactionScopeInsert, "Use SqlServer TransactionScope Insert");  
    52.     }  
    53.   
    54.     //使用表值参数   
    55.     private void btnTableTypeInsert_Click(object sender, EventArgs e)  
    56.     {  
    57.         Insert(DbOperation.ExecuteTableTypeInsert, "Use SqlServer TableType Insert");  
    58.     }  
    59.   
    60.     private DataTable InitDataTable()  
    61.     {  
    62.         DataTable table = Tools.MakeDataTable();  
    63.         int count = 0;  
    64.         if (int.TryParse(txtRecordCount.Text.Trim(), out count))  
    65.         {  
    66.             Tools.MakeData(table, count);  
    67.             //MessageBox.Show("Data Init OK");   
    68.         }  
    69.         return table;  
    70.     }  
    71.   
    72.     public void Insert(InsertHandler handler, string msg)  
    73.     {  
    74.         DataTable table = InitDataTable();  
    75.         if (table == null)  
    76.         {  
    77.             MessageBox.Show("DataTable is null");  
    78.             return;  
    79.         }  
    80.   
    81.         int recordCount = table.Rows.Count;  
    82.         if (recordCount <= 0)  
    83.         {  
    84.             MessageBox.Show("No Data");  
    85.             return;  
    86.         }  
    87.   
    88.         int batchSize = 0;  
    89.         int.TryParse(txtBatchSize.Text.Trim(), out batchSize);  
    90.         if (batchSize <= 0)  
    91.         {  
    92.             MessageBox.Show("batchSize <= 0");  
    93.             return;  
    94.         }  
    95.   
    96.         bool result = false;  
    97.         _watch.Reset(); _watch.Start();  
    98.         result = handler(table, batchSize);  
    99.         _watch.Stop(www.nuoya66.com);  
    100.         string log = string.Format("{0};RecordCount:{1};BatchSize:{2};Time:{3};", msg, recordCount, batchSize, _watch.ElapsedMilliseconds);  
    101.         LogHelper.Info(log);  
    102.         MessageBox.Show(result.ToString());  
    103.     }  
    104. }  
  • 相关阅读:
    Eclipse报错:An internal error has occurred. Widget is disposed
    服务器端解决跨域问题的三种方法
    为什么要使用NoSQL
    Mybatis 中$与#的区别
    maven 打包命令,跳过测试
    maven打包跳过测试命令
    Vue 扩展插件
    node 文件打开状态
    node buffer缓冲区
    npm 命令
  • 原文地址:https://www.cnblogs.com/zhcj0929/p/4424553.html
Copyright © 2011-2022 走看看