EFCore批量操作,你真的清楚吗

本文涉及的产品
RDS SQL Server Serverless,2-4RCU 50GB 3个月
推荐场景:
云数据库 RDS SQL Server,基础系列 2核4GB
简介: EntityFramework Core有许多新的特性,其中一个重要特性便是批量操作。批量操作意味着不需要为每次Insert/Update/Delete操作发送单独的命令,而是在一次SQL请求中发送批量组合指令。

背景


EntityFramework Core有许多新的特性,其中一个重要特性便是批量操作。批量操作意味着不需要为每次Insert/Update/Delete操作发送单独的命令,而是在一次SQL请求中发送批量组合指令。


EFCore批量操作实践


批处理是期待已久的功能,社区多次提出要求。现在EFCore支持开箱即用确实很棒,可以提高应用程序的性能和速度。


对比实践


以常见的批量插入为例,使用SQL Server Profiler观察产生并执行的SQL语句。

// category表添加3条记录并执行保存
using (var c= new SampleDBContext())
{
    c.Categories.Add(new Category() { CategoryID = 1, CategoryName = "Clothing" });
    c.Categories.Add(new Category() { CategoryID = 2, CategoryName = "Footwear" });
    c.Categories.Add(new Category() { CategoryID = 3, CategoryName = "Accessories" });
    c.SaveChanges();
}


当执行SaveChanges(), 从SQL Profiler追溯到的SQL

exec sp_executesql N'SET NOCOUNT ON;INSERT INTO [Categories] ([CategoryID], [CategoryName])
VALUES (@p0, @p1),(@p2, @p3),(@p4, @p5);',N'@p0 int,@p1 nvarchar(4000),@p2 int,@p3 nvarchar(4000),@p4 int,@p5 nvarchar(4000)',
@p0=1,@p1=N'Clothing',@p2=2,@p3=N'Footwear',@p4=3,@p5=N'Accessories'

如你所见,批量插入没有产生3个独立的语句,而是被组合为一个传参存储过程脚本(用列值作为参数);如果使用EF6执行相同的代码,则在SQL Server Profiler中将看到3个独立的插入语句 。下面EFCore、EF6批量插入的对比截图


9772369a0d9f7e079097a202a5eaae9b.png

88d00ed732203037d2406bdd35b72097.png


① 就性能和速度而言,EFCore批量插入更具优势

② 若数据库是针对云部署,EF6运行这些查询,还将产生额外的流量成本

经过验证:EFCore批量更新、批量删除功能,EFCore均发出了使用sp_executesql存储过程+批量参数构建的SQL脚本。


深入分析


起关键作用的存储过程sp_executesql:可以多次执行的语句或批处理 (可带参)

- Syntax for SQL Server, Azure SQL Database, Azure SQL Data Warehouse, Parallel Data Warehouse  
sp_executesql [ @stmt = ] statement  
[   
  { , [ @params = ] N'@parameter_name data_type [ OUT | OUTPUT ][ ,...n ]' }   
     { , [ @param1 = ] 'value1' [ ,...n ] }  
]


注意官方限制


The amount of data that can be passed by using this method is limited by the number of parameters allowed. SQL Server procedures can have, at most, 2100 parameters. Server-side logic is required to assemble these individual values into a table variable or a temporary table for processing.       // SQL存储过程最多可使用2100个参数


豁然开朗


SqlServer sp_executesql存储过程最多支持2100个批量操作形成的列值参数,所以遇到很大数量的批量操作,EFCore SqlProvider会帮我们将批量操作分块传输,这也是我们在实际大批量使用时看到分块发送的原因。


EFCore开放了【配置关系型数据库批量操作大小】

protected override void OnConfiguring(DbContextOptionsBuilder optionbuilder)
{
    string sConnString = @"Server=localhost;Database=EFSampleDB;Trusted_Connection=true;";
    optionbuilder.UseSqlServer(sConnString , b => b.MaxBatchSize(1));    // 批量操作的SQL语句数量,也可设定为1禁用批量插入}

总结


① EFCore 相比EF6,已经支持批量操作,能有效提高应用程序的性能

② EFCore的批量操作能力,由对应的DataBaseProvider支撑(Provider实现过程跟背后的存储载体密切相关);关注SQL存储过程sp_executesql,官方明文显示批量操作的列值参数最多2100个,这个关键因素决定了在大批量操作的时候 依旧会被分块传输。

③ 另外一个批量操作的方法,这里也点一下:构造Rawsql 【EFCore也支持Rawsql】

  sqlite不支持存储过程,为批量插入提高性能,可采用此方案

var insertStr = new StringBuilder();
insertStr.AppendLine("insert into ProfileUsageCounters (profileid,datetime,quota,usage,natureusage) values");
var txt = insertStr.AppendLine(string.Join(',', usgaeEntities.ToList().Select(x =>
{
       return $"({x.ProfileId},{x.DateTime},{x.Quota},{x.Usage},{x.NatureUsage})";
}).ToArray()));
await _context.Database.ExecuteSqlCommandAsync(txt.ToString());


相关实践学习
使用SQL语句管理索引
本次实验主要介绍如何在RDS-SQLServer数据库中,使用SQL语句管理索引。
SQL Server on Linux入门教程
SQL Server数据库一直只提供Windows下的版本。2016年微软宣布推出可运行在Linux系统下的SQL Server数据库,该版本目前还是早期预览版本。本课程主要介绍SQLServer On Linux的基本知识。 相关的阿里云产品:云数据库RDS SQL Server版 RDS SQL Server不仅拥有高可用架构和任意时间点的数据恢复功能,强力支撑各种企业应用,同时也包含了微软的License费用,减少额外支出。 了解产品详情: https://www.aliyun.com/product/rds/sqlserver
相关文章
|
开发框架 数据库 数据安全/隐私保护
FastAdmin框架实现数据表的增删改查
FastAdmin框架实现数据表的增删改查
564 0
|
SQL 前端开发 JavaScript
eggjs 怎么实现获取账单列表接口并且实现列表数据分页查询功能?
eggjs 怎么实现获取账单列表接口并且实现列表数据分页查询功能?
194 0
eggjs 怎么实现获取账单列表接口并且实现列表数据分页查询功能?
|
SQL 关系型数据库 MySQL
MySQL脚本命令数据简单增删改操作教程
MySQL脚本命令数据简单增删改操作教程
175 0
|
开发者
批量操作介绍|学习笔记
快速学习批量操作介绍。
|
JSON 数据格式 开发者
批量操作 bulk|学习笔记
快速学习批量操作 bulk。
131 0
|
API 开发者
批量操作介绍 | 学习笔记
快速学习批量操作介绍
|
SQL 存储 前端开发
使用DbContextPool提高EfCore查询性能
① 提示EFCore2.0新推出的DbContextPool特性,有效提高SQL查询吞吐量 ② 尝试使用SQL Server 内置脚本自证会话中有效连接数
使用DbContextPool提高EfCore查询性能
|
关系型数据库 MySQL 数据处理
thinkphp5的excel导入数据事务处理代码片段
thinkphp5的excel导入数据事务处理代码片段
|
SQL 数据库
EFCore-3
建模数据库,目前EFCore只支持Code First方法。
136 0