我有一个有趣的情况。当我在Microsoft SQL Server Management Studio中的远程SQL服务器上运行查询时,它运行很快(12秒),但是当我在 Entity Framework 中使用DbContext.Database.SqlQuery<EntityType>(script)
运行相同的查询时,则需要48秒。
我尝试设置set arithabort on
。设置已应用,但没有改变性能。我无法提供查询执行计划,因为我对SQL Server的权限有限。但是我可以100%地说这不是查询问题。
考虑以下查询:
declare @t table (...)
insert into @t
select <long query>
select top 1 * from @t
@t
变量包含约35k行。在EF和SSMS中,执行时间非常相似。但是,当我删除top 1
时,奇怪的事情开始发生。在SSMS中,我得到10秒,但是在EF中,我得到40秒。我猜想这个小实验可以排除SQL Server选择错误的执行计划并减慢运行速度的可能性。
另一个兴趣点是由EF完成的实体实现。我认为这也不是瓶颈,因为当我在本地SQL Express上运行具有类似大小的结果集的类似查询时,在两种情况下,我几乎都能立即获得结果。
因此,我的下一个猜测是网络问题。我安装了Microsoft Network Monitor 3.4,并监视了SSMS和EF的网络流量。我发现有趣的是,由于某种原因,存在许多较小的数据包,以及EF版本中的一些TLS数据包。在SSMS版本中,数据包大小更稳定,并且没有TLS数据包。
因此问题是:是否可以加快EF版本的速度?那些TLS数据包是什么,有可能摆脱它们吗?
更新
Entity Framework v6.1.3
.NET v4.5.1
SQL Server v10.50.2550.0
本地SQLExpress v12.0.4213.0
Windows 7专业版
更新
using (var connection = new SqlConnection(DbContext.Database.Connection.ConnectionString))
using (var cmd = new SqlCommand(script, connection))
{
connection.Open();
cmd.CommandType = CommandType.Text;
using (SqlDataReader reader = cmd.ExecuteReader())
{
reader.Read();
do
{
} while (reader.Read());
}
}
此代码在时间上产生相同的结果。
最佳答案
我已经进行了一些研究和实验,似乎在连接字符串中添加packet size=32768
(这是最大大小)选项趋向于将速度提高到几乎SSMS级别。有趣的是,我收到的TCP数据包而不是增加了它们的大小。
我也尝试了其他连接字符串选项,但没有收到任何明显的速度提高。