实体框架查询超级慢

时间:2016-05-15 00:26:47

标签: c# sql entity-framework

我正在从Log表中读取记录。该表目前有260,000条记录,共8列。这是通过EF6的代码。

using (var ctx = new DbEntities())
{
    ctx.Configuration.ProxyCreationEnabled = false;
    ctx.Configuration.AutoDetectChangesEnabled = false;
    ctx.Configuration.LazyLoadingEnabled = false;
    Stopwatch sw = Stopwatch.StartNew();
    var k = ctx.Logs.Where(l => l.ApplicationId == id && l.Level <= 3 && (l.Dat == 20160514 ||l.Dat == 20160513 ) ).ToList();
    sw.Stop();
}

以上需要7-8秒才能返回2213行。在SSMS上运行等效的故事不到一秒钟。

我也试过将查询作为

运行
ctx.Logs.SqlQuery("SELECT * FROM Log WITH(NOLOCK) WHERE ApplicationId = 4 and Level <= 3 and (Dat = 20160513 or Dat = 20160514)").AsNoTracking().ToList();

这也需要约7秒

我有2个非群集密钥,一个是ApplicationId DESC,另一个是ApplicationId DESC,Dat DESC,Level ASC。

活动监视器从不显示数据库上的负载。

对于此大小的查询,这似乎很长一段时间。或者我的期望是否有偏差?

任何人都可以看到我做错的事吗?

注意* Sql位于具有4个内核和8GB内存的Azure VM上,其内存为3GB

注意*我现在知道我不应该调用我的列级别

修改

以下内容来自EF6 Log

SELECT 
    [Extent1].[LogId] AS [LogId], 
    [Extent1].[ApplicationId] AS [ApplicationId], 
    [Extent1].[Type] AS [Type], 
    [Extent1].[Source] AS [Source], 
    [Extent1].[Message] AS [Message], 
    [Extent1].[LogTime] AS [LogTime], 
    [Extent1].[Level] AS [Level], 
    [Extent1].[Dat] AS [Dat]
    FROM [dbo].[Log] AS [Extent1]
    WHERE ([Extent1].[ApplicationId] = @p__linq__0) AND ([Extent1].[Level] <= 3) AND ([Extent1].[Dat] IN (20160514,20160513))
-- p__linq__0: '2648' (Type = Int32, IsNullable = false)
-- Executing at 5/14/2016 8:38:38 PM -04:00
-- Completed in 101 ms with result: SqlDataReader

看起来查询速度非常快。那么为什么ToList()这么慢?

3 个答案:

答案 0 :(得分:3)

EF必须将SQL的结果映射到对象中,这可能涉及反射和动态加载映射器以将SQL结果转换为logs列表。如果您计算单个结果,请尝试多次在同一个上下文中执行相同的操作。您会发现每个结果执行时间会减少。这是因为映射器已经加载,不需要检索。

我不是EF的专家,我只是尝试了同样的问题,发现几秒延迟只是第一次针对上下文执行的问题。

答案 1 :(得分:0)

在sql management studio上执行相同的查询

执行后点击“显示执行计划”按钮 enter image description here

阅读报告中的问题。 如果需要,执行修复添加缺失索引..

答案 2 :(得分:-1)

经过一些试验和错误,我发现我可以减少至少一半的时间。

首先进行Count()调用,然后我可以将请求分成多个部分,并以较小的增量逐页请求。

所以同样的2213个项目现在需要3-4秒才能并行进行两次调用,每个只有1000个。 10,000件物品过去需要60秒,这种方法约为18秒。

ds = pd.Series(['a','ab','b','a'])
ds
0     a
1    ab
2     b
3     a
dtype: object

ds.apply(lambda x: 1 if 'b' in x else 0)
0    0
1    1
2    1
3    0
dtype: int64

小于1000似乎没有给出更好的结果。