海量数据操作ORM性能瓶颈在实体转换上面,并且不能使用常规的Sql去实现
当列越多转换越慢,SqlSugar将转换性能做到极致,并且采用数据库最佳API
操作数据库达到极限性能
正常使用如下:
db.Fastest<DC_Scene>().BulkCopy(lstData);//插入 db.Fastest<RealmAuctionDatum>().BulkUpdate(GetList())//更新 //db.Queryable<Order>().ToList();大数据查询也很快 比Dapper略快 //更多用法看 标题2 :支持 更新、分页等 //超过50万 占内存大 这个时候可以试试分页 db.Fastest<Order>().PageSize(300000).BulkCopy(insertObjs);
WinFom用法:
//WinFrom中 不能直接用,会出现卡住不动,因为WinFrom不支持直接调用异步 ,需要加委托 //bulkCopy 和 bulkCopyAsync 底层都是异步实现 Func<int> func = () =>db.Fastest<DC_Scene>().BulkCopy(lstData); func.BeginInvoke(x=> { var result = func.EndInvoke(x);//获取返回值 MessageBox.Show($"成功添加数据:{result}条"); }, null);
注意:winform写法有点区别看一下不同点
//插入 100万 10秒不到 db.Fastest<RealmAuctionDatum>().BulkCopy(GetList());//性能比 EFCore.Bulkextension 快30% (列越多差距越大) //使用datatable 5.0.7.7 db.Fastest<System.Data.DataTable>().AS("order").BulkCopy(dataTable); //更新 db.Fastest<RealmAuctionDatum>().BulkUpdate(GetList());//是 EFCore.Bulkextension 2-3倍,30列100万8秒更新完 db.Fastest<Test001_model>().BulkUpdate(GetList(),new string[] { "name"});//只更新固定列,需要有主键 db.Fastest<RealmAuctionDatum>().BulkUpdate(GetList(),new string[]{"id"},new string[]{"name","time"})//无主键用法 //注意:更新情况比较复杂,有些表会出现比较慢的情况 //主键尽量用(没主键性能会慢) long或者int ,然后 list在内存中按主键排序在传给ORM //然后设置.PageSize(1000).BulkUpdate(GetList()) 进行内部分页更新 //表设置别名 db.Fastest<RealmAuctionDatum>().AS("tableName").BulkCopy(GetList()) //分页 db.Fastest<Order>().PageSize(300000).BulkCopy(insertObjs); //MySql utf8mb4 db.Fastest<Order>().SetCharacterSet("utf8mb4").BulkCopy(insertObjs)
插入的列越多,越能体现性能
Db.Fastest.BulkCopy 比 EFCore.Bulkextension 快30% 插入的列的数量越多越强
Db.Fastest.BulkUpdate 是 EFCore.Bulkextension 2-3倍
SqlSugar>EFCore.Bulkextension>Dapper (ef plus & dapper plus 收费框架 未进行测试)
注意:不支持默认值和计算列
数据库 | API | 支持自增 | 使用说明 |
SqlSever | 全支持 | 是 | |
MySql | 全支持 | 是 | 连接字符串要加AllowLoadLocalInfile=true |
PgSql | 全支持 | 否 | 不支持自增或者特殊默认值 |
Oracle | 全支持 5.0.4.7 只支持 .NET CORE | 否 | 缺点:不支持事务,无视唯一索引可以插入重复数据,尽量用GUID或者雪花ID,调试不要来回拖断点防止插入重复数据 破坏索引 出错后方案: 删除主键 1.alter table TESTFAST11 drop primary key 2.找出重复数据删掉 3.在重新创建索引 推荐:下面写法性能可以满足尽量用下面写法 db.Insertable(List<实体>).UseParameter().ExecuteCommand() |
Sqlite | 全支持 5.0.5.3 | 是 |
对于海量数据并且性能要高的可以用下面的方式实现更新保存功能
//一起写 : 5.1.4.62 db.Storageable<Order>(data).ExecuteSqlBulkCopy() //分开写 var x= db.Storageable<Order>(data).ToStorage();//最好是主键为条件 varchar小于50 x.BulkCopy();//不存在插入 x.BulkUpdate();//存在更新 //winform写法需要注意 ,文档最上面
注意:返回前端雪花ID要转成String,不然前端精度不够(文档插入有细讲)
SnowFlakeSingle.Instance.NextId(); //目前需要实体手动赋值 //多台服务器同时插入一个库需要配置服务器唯一ID //SnowFlakeSingle.WorkId=不同机器配置的唯一数字
并发高用异步方法吐能量能提高
一次插入的数据量越大他的价值越高,比如1000以下就不合算了,数据量小的时候并发吞吐量不如普通插入
await db.Fastest<RealmAuctionDatum>().BulkCopyAsync(GetList()) //用异步await不能少 await db.Fastest<RealmAuctionDatum>().BulkUpdateAsync(GetList()) //winform写法需要注意 ,文档最上面
db.Fastest<OrderSpliteTest>().SplitTable().BulkCopy(List<OrderSpliteTest>); db.Fastest<OrderSpliteTest>().SplitTable().BulkUpdate(List<OrderSpliteTest>); //实体定义看分表文档 //winform写法需要注意与上面 文档最上面
分页可以降低内存占用
//如果数据库现有数据比较多出现比较慢,这个时候可以试试分页 db.Fastest<Order>().PageSize(300000).BulkCopy(insertObjs);
老版本可以这么用,性能不如db.Fastest
//(3)、blukCopy插入 //只适合1万以上超大数据插入或者上面数据插入慢情况,小数据插入性能不行,不是所有库都支持 db.Insertable(List<实体>).UseSqlServer().ExecuteBulkCopy() db.Insertable(List<实体>).UseMySql().ExecuteBulkCopy()//高版本Mysql.data驱动,连接字符串要加AllowLoadLocalInfile=true db.Insertable(List<实体>).UseOracle().ExecuteBulkCopy()//5.0.3.8-Preview //SqlBulkCopy
2016 © donet5.comApache Licence 2.0