Entity Framework调用存储过程超时问题求助
这种情况我之前排查过好几次,给你列几个最可能的排查方向,一步步来定位问题:
检查参数嗅探与执行计划差异
直接在数据库执行存储过程时用的参数,和EF传递的参数是不是完全一致?有时候EF会隐式转换参数类型(比如把.NET的string转成nvarchar,但存储过程参数定义的是varchar),或者参数值的数据分布差异大,导致SQL Server生成了低效的执行计划。
可以先试试临时解决方案:在存储过程的查询语句末尾加OPTION (RECOMPILE),或者在存储过程内部用局部变量接收输入参数后再使用,看看能不能让执行计划重新生成并匹配当前参数。核对连接字符串与连接配置
确认EF使用的连接字符串和你直接执行时用的是不是同一个数据库实例?有没有可能EF走的是远程网络连接,而你直接操作是本地服务器?另外检查连接字符串里的配置:比如是否开启了MultipleActiveResultSets,连接池是否正常工作(有没有每次调用都重新创建连接的情况)。可以在EF调用前后加日志,记录连接建立的耗时。排查EF调用方式的额外开销
你是用Database.SqlQuery还是DbSet.FromSqlRaw来调用存储过程的?如果返回的实体数量较多,EF的变更跟踪会带来不小的内存开销——试试在调用后加上.AsNoTracking()关闭跟踪,看看耗时有没有下降。另外要区分清楚:是数据库查询本身慢,还是EF把查询结果转换成实体/后续处理的过程慢?可以单独计时数据库调用部分(比如只执行ExecuteSqlRaw而不返回实体)来验证。验证网络与数据库端实际耗时
直接在数据库服务器执行是本地操作,EF的应用服务器到数据库服务器的网络可能存在延迟。可以用SQL Server Profiler或者Extended Events跟踪EF发起的请求,看看数据库端实际执行这个存储过程的耗时是多少——如果数据库端执行还是不到1秒,那问题就出在网络传输或者EF客户端的处理上;如果数据库端执行也慢,那就是执行计划或者参数的问题。查看执行计划缓存
用SQL Server的系统视图查看存储过程的执行计划缓存:SELECT cp.plan_handle, st.text, qp.query_plan FROM sys.dm_exec_cached_plans cp CROSS APPLY sys.dm_exec_sql_text(cp.plan_handle) st CROSS APPLY sys.dm_exec_query_plan(cp.plan_handle) qp WHERE st.text LIKE '%你的存储过程名称%'对比EF调用和直接执行时使用的执行计划是否一致,如果不一致,那就是计划生成的问题,回到参数嗅探的排查方向。
开启EF详细日志
开启EF的日志功能,查看生成的SQL语句是不是和你直接执行的完全一致?有没有EF自动添加的额外过滤、连接逻辑?比如有些情况下EF会对返回的结果做额外的处理,这部分也可能带来耗时。
先从这些方向入手排查,应该能快速定位到问题根源。
内容的提问来源于stack exchange,提问作者Andrew

