net core天马行空系列-各大数据库快速批量插入数据方法汇总 ...

打印 上一主题 下一主题

主题 897|帖子 897|积分 2691

1.前言

hi,大家好,我是三合。我是怎么想起写一篇关于数据库快速批量插入的博客的呢?事情起源于我们工作中的一个需求,简单来说,就是有一个定时任务,从数据库里获取大量数据,在应用层面经过处理后再把结果批量插入回到数据库里。这个任务每十分钟执行一次,但是有的时候数据量太大,循环插入数据库的时候会超时,导致任务失败,所以这个时候我就开始研究怎么快速批量插入数据库,因为我们用的数据库是Oracle,所以我首先研究了Oracle的快速批量插入,后面我一想那其他类型的数据库肯定也有这样的需求,于是我在找了很多资料,并且反复实验后,终于完美解决了mysql,sqlServer以及Oracle的快速批量插入,sqlite自身不支持,所以没有sqlite,特地整理成这篇文章,分享给大家。
2.测试前准备

添加一个具有绝大多数类型属性的实体类,用来完整测验批量插入效果,该实体类用于mysql和sqlserver的测试。
  1. public class NullableTable
  2. {
  3.     [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
  4.     [Key]
  5.     public int Id { get; set; }
  6.     [Description("Int2")]
  7.     public int? Int2 { get; set; }
  8.     [Description("Long2")]
  9.     public long? Long2 { get; set; }
  10.     public float? Float2 { get; set; }
  11.     public double? Double2 { get; set; }
  12.     public decimal? Decimal2 { get; set; }
  13.     [DecimalPrecision(20,4)]
  14.     public decimal? Decimal3 { get; set; }
  15.     public Guid? Guid2 { get; set; }
  16.     public short? Short2 { get; set; }
  17.     public DateTime? DateTime2 { get; set; }
  18.     public bool? Bool2 { get; set; }
  19.     public TimeSpan? TimeSpan2 { get; set; }
  20.     public byte? Byte2 { get; set; }
  21.     [StringLength(100)]
  22.     public string String2 { get; set; }
  23.     public string String3 { get; set; }
  24.     public Enum2? Enum2 { get; set; }
  25.     [Column("TestInt3")]
  26.     [Description("Int2")]
  27.     public int? Int3 { get; set; }
  28. }
  29. public enum Enum2
  30.     {
  31.         x,
  32.         y
  33.     }
复制代码
因为oracle数据库我们习惯于表名和字段名大写,所以oracle的测试实体类定义如下:
  1. [Table("NULLABLETABLE")]
  2. [Description("NullableTable")]
  3. public class NullableTable
  4. {
  5.     [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
  6.     [Key]
  7.     [Column("ID")]
  8.     public int Id { get; set; }
  9.     [Description("Int2")]
  10.     [Column("INT2")]
  11.     public int? Int2 { get; set; }
  12.     [Description("Long2")]
  13.     [Column("LONG2")]
  14.     public long? Long2 { get; set; }
  15.     [Column("FLOAT2")]
  16.     public float? Float2 { get; set; }
  17.     [Column("DOUBLE2")]
  18.     public double? Double2 { get; set; }
  19.     [Column("DECIMAL2")]
  20.     public decimal? Decimal2 { get; set; }
  21.     [Column("DECIMAL3")]
  22.     [DecimalPrecision(20,4)]
  23.     public decimal? Decimal3 { get; set; }
  24.     [Column("GUID2")]
  25.     public Guid? Guid2 { get; set; }
  26.     [Column("SHORT2")]
  27.     public short? Short2 { get; set; }
  28.     [Column("DATETIME2")]
  29.     public DateTime? DateTime2 { get; set; }
  30.     [Column("BOOL2")]
  31.     public bool? Bool2 { get; set; }
  32.     [Column("TIMESPAN2")]
  33.     public TimeSpan? TimeSpan2 { get; set; }
  34.     [Column("BYTE2")]
  35.     public byte? Byte2 { get; set; }
  36.     [Column("STRING2")]
  37.     [StringLength(100)]
  38.     public string String2 { get; set; }
  39.     [Column("STRING3")]
  40.     public string String3 { get; set; }
  41.     [Column("ENUM2")]
  42.     public Enum2? Enum2 { get; set; }
  43.     [Column("TESTINT3")]
  44.     [Description("Int2")]
  45.     public int? Int3 { get; set; }
  46. }
复制代码
实验我们采用的是code first,先利用SummerBoot框架的可用于依赖注入的,数据库表和c#实体类互相转换的接口实现功能从实体类生成相应的数据库表,本次实验批量插入2w条数据来对比时间,定义一个列表,用循环的方式给这个列表添加2w条数据。
  1. var nullableTableList3 = new List<NullableTable>();
  2. var now = DateTime.Now;
  3. for (int i = 0; i < 20000; i++)
  4. {
  5.     var a = new NullableTable()
  6.     {
  7.         Int2 = 2,
  8.         Bool2 = true,
  9.         Byte2 = 1,
  10.         DateTime2 = now,
  11.         Decimal2 = 1m,
  12.         Decimal3 = 1.1m,
  13.         Double2 = 1.1,
  14.         Float2 = (float)1.1,
  15.         Guid2 = Guid.NewGuid(),
  16.         Id = 0,
  17.         Short2 = 1,
  18.         TimeSpan2 = TimeSpan.FromHours(1),
  19.         String2 = "sb",
  20.         String3 = "sb",
  21.         Long2 = 2,
  22.         Enum2 = Model.Enum2.y,
  23.         Int3 = 4
  24.     };
  25.     nullableTableList3.Add(a);
  26. }
复制代码
数据库驱动上的选择是这样的,sqlserver采用微软官方驱动System.Data.SqlClient,oracle采用官方驱动Oracle.ManagedDataAccess.Core,mysql采用社区驱动MySqlConnector(为啥mysql不采用官方的驱动呢?因为官方的驱动封装的太差了,社区的驱动支持列名映射,同时项目里官方驱动和社区驱动可以共存)。
同时快速批量插入均支持异步同步,这里仅演示同步,异步的实现基本一样。
3.sqlserver快速批量插入

sqlserver官方提供的批量插入方式是SqlBulkCopy,参数为一个dataTable对象,原生的批量插入代码如下,采用StopWatch类进行计时,测试前都会用DELETE  from NullableTable 语句清空表,测试里循环跑5次,获取总时间后除以5获取平均值,合计插入10w条数据。
  1. var sw = new Stopwatch();
  2. sw.Start();
  3. for (int i = 0; i < 5; i++)
  4. {
  5.   using (var dbConnection = new SqlConnection(connectionString))
  6.   {
  7.       dbConnection.Open();
  8.       SqlBulkCopy sqlBulkCopy = new SqlBulkCopy(dbConnection, SqlBulkCopyOptions.KeepIdentity,
  9.           null);
  10.       sqlBulkCopy.BatchSize = 20000;
  11.       sqlBulkCopy.DestinationTableName = "NullableTable";
  12.       //针对列名做一下映射
  13.       sqlBulkCopy.ColumnMappings.Add("Int2", "Int2");
  14.       sqlBulkCopy.ColumnMappings.Add("Bool2", "Bool2");
  15.       sqlBulkCopy.ColumnMappings.Add("Byte2", "Byte2");
  16.       sqlBulkCopy.ColumnMappings.Add("DateTime2", "DateTime2");
  17.       sqlBulkCopy.ColumnMappings.Add("Decimal2", "Decimal2");
  18.       sqlBulkCopy.ColumnMappings.Add("Decimal3", "Decimal3");
  19.       sqlBulkCopy.ColumnMappings.Add("Double2", "Double2");
  20.       sqlBulkCopy.ColumnMappings.Add("Float2", "Float2");
  21.       sqlBulkCopy.ColumnMappings.Add("Guid2", "Guid2");
  22.       sqlBulkCopy.ColumnMappings.Add("Short2", "Short2");
  23.       sqlBulkCopy.ColumnMappings.Add("TimeSpan2", "TimeSpan2");
  24.       sqlBulkCopy.ColumnMappings.Add("String2", "String2");
  25.       sqlBulkCopy.ColumnMappings.Add("String3", "String3");
  26.       sqlBulkCopy.ColumnMappings.Add("Long2", "Long2");
  27.       sqlBulkCopy.ColumnMappings.Add("Enum2", "Enum2");
  28.       sqlBulkCopy.ColumnMappings.Add("Int3", "TestInt3");
  29.       //将实体类列表转换成dataTable
  30.       var table = nullableTableList3.ToDataTable();
  31.       sqlBulkCopy.WriteToServer(table);
  32.   }
  33. }
  34. sw.Stop();            
  35. var totalTime= sw.ElapsedMilliseconds;
  36. var avgValue = totalTime / 5;
复制代码
实验结果如下,sql server中:
采用快速批量插入10w条数据,时间合计1858毫秒,平均插入2w条数据仅需371毫秒。
采用insert into语句,循环插入10w条数据,时间合计457606毫秒,平均插入2w条数据需91521毫秒。
4.实体类列表转dataTable的扩展方法

这里有一个实体类列表转dataTable的扩展方法,采用的是表达式树+构建委托的方式,性能不错,大家可以参考,代码实现如下。
  1. public static ConcurrentDictionary<string, object> CacheDictionary = new ConcurrentDictionary<string, object>();
  2. /// <summary>
  3. /// 构建一个object数据转换成一维数组数据的委托
  4. /// </summary>
  5. /// <param name="objType"></param>
  6. /// <param name="propertyInfos"></param>
  7. /// <returns></returns>
  8. public static Func<T, object[]> BuildObjectGetValuesDelegate<T>(List<PropertyInfo> propertyInfos) where T : class
  9. {
  10.     var objParameter = Expression.Parameter(typeof(T), "model");
  11.     var selectExpressions = propertyInfos.Select(it => BuildObjectGetValueExpression(objParameter, it));
  12.     var arrayExpression = Expression.NewArrayInit(typeof(object), selectExpressions);
  13.     var result = Expression.Lambda<Func<T, object[]>>(arrayExpression, objParameter).Compile();
  14.     return result;
  15. }
  16. /// <summary>
  17. /// 构建对象获取单个值得
  18. /// </summary>
  19. /// <param name="modelExpression"></param>
  20. /// <param name="propertyInfo"></param>
  21. /// <returns></returns>
  22. public static Expression BuildObjectGetValueExpression(ParameterExpression modelExpression, PropertyInfo propertyInfo)
  23. {
  24.     var propertyExpression = Expression.Property(modelExpression, propertyInfo);
  25.     var convertExpression = Expression.Convert(propertyExpression, typeof(object));
  26.     return convertExpression;
  27. }
  28. public static DataTable ToDataTable<T>(this IEnumerable<T> source, List<PropertyInfo> propertyInfos = null,bool useColumnAttribute=false) where T : class
  29. {
  30.     var table = new DataTable("template");
  31.     if (propertyInfos == null || propertyInfos.Count == 0)
  32.     {
  33.         propertyInfos = typeof(T).GetProperties().Where(it => it.CanRead).ToList();
  34.     }
  35.     foreach (var propertyInfo in propertyInfos)
  36.     {
  37.         var columnName=useColumnAttribute?(propertyInfo.GetCustomAttribute<ColumnAttribute>()?.Name?? propertyInfo.Name) : propertyInfo.Name;
  38.         table.Columns.Add(columnName, ChangeType(propertyInfo.PropertyType));
  39.     }
  40.     Func<T, object[]> func;
  41.     var key = typeof(T).FullName + propertyInfos.Select(it => it.Name).ToList().StringJoin();
  42.     if (CacheDictionary.TryGetValue(key, out var cacheFunc))
  43.     {
  44.         func = (Func<T, object[]>)cacheFunc;
  45.     }
  46.     else
  47.     {
  48.         func = BuildObjectGetValuesDelegate<T>(propertyInfos);
  49.         CacheDictionary.TryAdd(key, func);
  50.     }
  51.     foreach (var model in source)
  52.     {
  53.         var rowData = func(model);
  54.         table.Rows.Add(rowData);
  55.     }
  56.     return table;
  57. }
  58. private static Type ChangeType(Type type)
  59. {
  60.     if (type.IsNullable())
  61.     {
  62.         type = Nullable.GetUnderlyingType(type);
  63.     }
  64.     return type;
  65. }
复制代码
5.oracle快速批量插入

oracle官方提供的批量插入方式是ArrayBindCount,即数组批量插入,原生的批量插入代码如下,计时方式与sqlserver相同
  1. var total = 20000;
  2. var sw = new Stopwatch();
  3. sw.Start();
  4. for (int i = 0; i < 5; i++)
  5. {
  6.     var connection = new OracleConnection(connectionString);
  7.     connection.Open();
  8.     int?[] Int2 = new int?[total];
  9.     bool[] Bool2 = new bool[total];
  10.     byte[] Byte2 = new byte[total];
  11.     DateTime[] DateTime2 = new DateTime[total];
  12.     decimal?[] Decimal2 = new decimal?[total];
  13.     decimal[] Decimal3 = new decimal[total];
  14.     double[] Double2 = new double[total];
  15.     float[] Float2 = new float[total];
  16.     Guid?[] Guid2 = new Guid?[total];
  17.     short[] Short2 = new short[total];
  18.     TimeSpan[] TimeSpan2 = new TimeSpan[total];
  19.     string[] String2 = new string[total];
  20.     string[] String3 = new string[total];
  21.     long[] Long2 = new long[total];
  22.     Enum2[] Enum2 = new Enum2[total];
  23.     for (int j = 0; j < total; j++)
  24.     {
  25.         Int2[j] = 2;
  26.         Bool2[j] = true;
  27.         Byte2[j] = 1;
  28.         DateTime2[j] = now;
  29.         Decimal2[j] = 1m;
  30.         Decimal3[j] = 1.1m;
  31.         Double2[j] = 1.1;
  32.         Float2[j] = (float) 1.1;
  33.         Guid2[j] = Guid.NewGuid();
  34.         Short2[j] = 1;
  35.         TimeSpan2[j] = TimeSpan.FromHours(1);
  36.         String2[j] = "sb";
  37.         String3[j] = "sb";
  38.         Long2[j] = 2;
  39.         Enum2[j] = Model.Enum2.y;
  40.     }
  41.     var c = (int) Model.Enum2.y;
  42.     OracleParameter pInt2 = new OracleParameter();
  43.     pInt2.OracleDbType = OracleDbType.Int32;
  44.     pInt2.Value = Int2;
  45.     OracleParameter pBool2 = new OracleParameter();
  46.     pBool2.OracleDbType = OracleDbType.Byte;
  47.     pBool2.Value = Bool2;
  48.     OracleParameter pByte2 = new OracleParameter();
  49.     pByte2.OracleDbType = OracleDbType.Byte;
  50.     pByte2.Value = Byte2;
  51.     OracleParameter pDateTime2 = new OracleParameter();
  52.     pDateTime2.OracleDbType = OracleDbType.TimeStamp;
  53.     pDateTime2.Value = DateTime2;
  54.     OracleParameter pDecimal2 = new OracleParameter();
  55.     pDecimal2.OracleDbType = OracleDbType.Decimal;
  56.     pDecimal2.Value = Decimal2;
  57.     OracleParameter pDecimal3 = new OracleParameter();
  58.     pDecimal3.OracleDbType = OracleDbType.Decimal;
  59.     pDecimal3.Value = Decimal3;
  60.     OracleParameter pDouble2 = new OracleParameter();
  61.     pDouble2.OracleDbType = OracleDbType.Double;
  62.     pDouble2.Value = Double2;
  63.     OracleParameter pFloat2 = new OracleParameter();
  64.     pFloat2.OracleDbType = OracleDbType.BinaryFloat;
  65.     pFloat2.Value = Float2;
  66.     OracleParameter pGuid2 = new OracleParameter();
  67.     pGuid2.OracleDbType = OracleDbType.Raw;
  68.     pGuid2.Value = Guid2;
  69.     OracleParameter pShort2 = new OracleParameter();
  70.     pShort2.OracleDbType = OracleDbType.Int16;
  71.     pShort2.Value = Short2;
  72.     OracleParameter pTimeSpan2 = new OracleParameter();
  73.     pTimeSpan2.OracleDbType = OracleDbType.IntervalDS;
  74.     pTimeSpan2.Value = TimeSpan2;
  75.     OracleParameter pString2 = new OracleParameter();
  76.     pString2.OracleDbType = OracleDbType.Varchar2;
  77.     pString2.Value = String2;
  78.     OracleParameter pString3 = new OracleParameter();
  79.     pString3.OracleDbType = OracleDbType.Varchar2;
  80.     pString3.Value = String3;
  81.     OracleParameter pLong2 = new OracleParameter();
  82.     pLong2.OracleDbType = OracleDbType.Long;
  83.     pLong2.Value = Long2;
  84.     OracleParameter pEnum2 = new OracleParameter();
  85.     pEnum2.OracleDbType = OracleDbType.Byte;
  86.     pEnum2.Value = Enum2;
  87.     // create command and set properties
  88.     OracleCommand cmd = connection.CreateCommand();
  89.     cmd.CommandText =
  90.         "INSERT INTO NULLABLETABLE (INT2, LONG2, FLOAT2, DOUBLE2, DECIMAL2, DECIMAL3, GUID2, SHORT2, DATETIME2, BOOL2, TIMESPAN2, BYTE2, STRING2, STRING3,ENUM2) VALUES(:1,:2,:3,:4,:5,:6,:7,:8,:9,:10,:11,:12,:13,:14,:15)";
  91.     cmd.ArrayBindCount = total;
  92.     cmd.Parameters.Add(pInt2);
  93.     cmd.Parameters.Add(pLong2);
  94.     cmd.Parameters.Add(pFloat2);
  95.     cmd.Parameters.Add(pDouble2);
  96.     cmd.Parameters.Add(pDecimal2);
  97.     cmd.Parameters.Add(pDecimal3);
  98.     cmd.Parameters.Add(pGuid2);
  99.     cmd.Parameters.Add(pShort2);
  100.     cmd.Parameters.Add(pDateTime2);
  101.     cmd.Parameters.Add(pBool2);
  102.     cmd.Parameters.Add(pTimeSpan2);
  103.     cmd.Parameters.Add(pByte2);
  104.     cmd.Parameters.Add(pString2);
  105.     cmd.Parameters.Add(pString3);
  106.     cmd.Parameters.Add(pEnum2);
  107.     cmd.ExecuteNonQuery();
  108. }
  109. sw.Stop();
  110. var totalTime = sw.ElapsedMilliseconds;
  111. var avgValue = totalTime / 5;
复制代码
实验结果如下,oracle中:
采用快速批量插入10w条数据,时间合计2323毫秒,平均插入2w条数据仅需464毫秒。
采用insert into语句,循环插入10w条数据,时间合计462837毫秒,平均插入2w条数据仅需92567毫秒。
6.mysql快速批量插入

mysql社区驱动MySqlConnector提供的批量插入方式是SqlBulkCopy,基于mysql自身的文件上传机制进行批量插入,参数为一个dataTable对象,原生的批量插入代码如下,计时方式与sqlserver相同,同时,mysql的连接字符串里要添加";AllowLoadLocalInfile=true",即连接字符串的形式应该是"Server= ;Database=;User ID=;Password=;AllowLoadLocalInfile=true",同时在mysql数据库上执行"set global local_infile=1"开启批量上传
  1. var sw = new Stopwatch();
  2. sw.Start();
  3. for (int j = 0; j < 5; j++)
  4. {
  5.     using (var dbConnection = new MySqlConnection(connectionString))
  6.     {
  7.         dbConnection.Open();
  8.         MySqlBulkCopy sqlBulkCopy = new MySqlBulkCopy(dbConnection, null);
  9.         sqlBulkCopy.DestinationTableName = "NullableTable";
  10.         var propertys = typeof(NullableTable).GetProperties()
  11.             .Where(it => it.CanRead && it.GetCustomAttribute<NotMappedAttribute>() == null).ToList();
  12.         for (int i = 0; i < propertys.Count; i++)
  13.         {
  14.             var property = propertys[i];
  15.             var columnName = property.GetCustomAttribute<ColumnAttribute>()?.Name ?? property.Name;
  16.             if (property.PropertyType.GetUnderlyingType() == typeof(Guid))
  17.             {
  18.                 sqlBulkCopy.ColumnMappings.Add(new MySqlBulkCopyColumnMapping(i, "@tmp",
  19.                     $"{columnName} =unhex(@tmp)"));
  20.             }
  21.             else
  22.             {
  23.                 sqlBulkCopy.ColumnMappings.Add(new MySqlBulkCopyColumnMapping(i, columnName));
  24.             }
  25.         }
  26.         var table = nullableTableList3.ToDataTable();
  27.         SbUtil.ReplaceDataTableColumnType<Guid, byte[]>(table, guid1 => guid1.ToByteArray());
  28.         var c = sqlBulkCopy.WriteToServer(table);
  29.     }
  30. }
  31. sw.Stop();
  32. var totalTime = sw.ElapsedMilliseconds;
  33. var avgValue = totalTime / 5;
复制代码
实验结果如下,mysql中:
采用快速批量插入10w条数据,时间合计2350毫秒,平均插入2w条数据仅需470毫秒。
采用insert into语句,循环插入10w条数据,时间合计414700毫秒,平均插入2w条数据需82940毫秒。
在mysql中c#的guid对应的mysql字段类型为varbinary(16),所以table里的guid要转换为字节数组,否则插入数据库后,guid的值就会变成乱码,字节数组传递到mysql服务端后利用unhex函数进行解析,即可正常保存guid类型。 将table里guid的值转为字节数组的方法-SbUtil.ReplaceDataTableColumnType的代码实现如下:
  1. /// <summary>
  2. /// 替换dataTable里的列类型
  3. /// </summary>
  4. /// <param name="dt"></param>
  5. public  static void ReplaceDataTableColumnType<OldType,NewType>(DataTable dt,Func<OldType, NewType> replaceFunc)
  6. {
  7.     var needUpdateColumnIndexList = new List<int>();
  8.     var needUpdateColumnNameList = new List<string>();
  9.    
  10.     for (int i = 0; i < dt.Columns.Count; i++)
  11.     {
  12.         var column = dt.Columns[i];
  13.         if (column.DataType.GetUnderlyingType() == typeof(OldType))
  14.         {
  15.             needUpdateColumnIndexList.Add(i);
  16.             needUpdateColumnNameList.Add(column.ColumnName);
  17.          
  18.         }
  19.     }
  20.     if (needUpdateColumnIndexList.Count == 0)
  21.     {
  22.         return;
  23.     }
  24.     var nameMapping = new Dictionary<string, string>();
  25.     for (int i = 0; i < needUpdateColumnIndexList.Count; i++)
  26.     {
  27.         var oldColumnName = needUpdateColumnNameList[i];
  28.         var newColumnName = Guid.NewGuid().ToString("N");
  29.         nameMapping.Add(newColumnName, oldColumnName);
  30.       
  31.         dt.Columns.Add(newColumnName, typeof(byte[])).SetOrdinal(needUpdateColumnIndexList[i]);
  32.         for (int j = 0; j < dt.Rows.Count; j++)
  33.         {
  34.             var c = (dt.Rows[j][oldColumnName]);
  35.             dt.Rows[j][newColumnName] = replaceFunc((OldType)(dt.Rows[j][oldColumnName]));
  36.         }
  37.         dt.Columns.Remove(oldColumnName);
  38.     }
  39.    
  40.     for (int i = 0; i < dt.Columns.Count; i++)
  41.     {
  42.         var columnName = dt.Columns[i].ColumnName;
  43.         if (nameMapping.ContainsKey(columnName))
  44.         {
  45.             dt.Columns[i].ColumnName = nameMapping[columnName];
  46.         }
  47.     }
  48. }
复制代码
7.SummerBoot对各数据库快速批量插入的封装

基于以上各种数据库对于快速批量插入的原生写法过于复杂难记,SummerBoot对其进行了封装,在声明式编程的理念下,封装后仅需3步即可快速批量插入,这里以sqlserver举例。
7.1在StartUp.cs中添加summerBoot的服务支持
  1. services.AddSummerBoot();
  2. services.AddSummerBootRepository(it =>
  3. {
  4.     it.DbConnectionType = typeof(SqlConnection);
  5.     it.ConnectionString = connectionString;
  6. });
复制代码
7.2添加仓储接口
  1. [AutoRepository]
  2. public interface INullableTableRepository : IBaseRepository<NullableTable>
  3. {
  4.    
  5. }
复制代码
7.3注入仓储接口后直接调用FastBatchInsert方法
  1. var sw = new Stopwatch();
  2. sw.Start();
  3. for (int i = 0; i < 5; i++)
  4. {
  5.     nullableTableRepository.FastBatchInsert(nullableTableList3);
  6. }
  7. sw.Stop();
  8.   
  9. var totalTime= sw.ElapsedMilliseconds;
  10. var avgValue = totalTime / 5;
复制代码
实验结果如下,sql server中:
采用SummerBoot统一封装后快速批量插入10w条数据,时间合计3926(原生快速批量写法1858)毫秒,平均插入2w条数据仅需785(原生快速批量写法371)毫秒。从对比可以看出,经过SummerBoot封装后,快速批量插入所花费的时间有所增加,但是对于这么大数据量而言,这点多消耗的时间和节省的开发量对比,不值一提。
写在最后

SummerBoot是一款声明式编程框架,专注于”做什么”而不是”如何去做”,更多用法,可参考SummerBoot文档,也可以加入QQ群:799648362反馈建议。同时各位看官,如果你觉得这篇文章还不错的话,请帮忙一键三连哦(推荐+关注+github star)

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

老婆出轨

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表