2016-10-11 46 views
2

因此,有一些关于实体框架6的MySQL插件性能的抱怨。然而,其中的大部分似乎归结为它产生了不好的SQL。我遇到了这个问题,但这似乎是由于插件本身的性能滞后。实体框架6 MySQL - 与MySQL引擎相比的性能差异

这里是我的查询在LINQ:

List<Address> matches = _rep.GetAddresses(s => s.AddressKey == cleanAddress).ToList(); 

,在库(_rep)我有这样的:

public IQueryable<Address> GetAddresses(Expression<Func<Address, bool>> query) 
{ 
    //var foo = Addresses.AsNoTracking().Where(query); 
    //var bar = foo.ToString(); 

    return Addresses.AsNoTracking().Where(query); 
} 

所以我已经使用AsNoTracking尝试和改进的性能。注释掉的行在那里,所以我可以看到正在生成的SQL,结果如下:

SELECT 
`Extent1`.`AddressId`, 
`Extent1`.`AddressKey`, 
`Extent1`.`NameKey`, 
`Extent1`.`Title`, 
`Extent1`.`Forename`, 
`Extent1`.`Surname`, 
FROM `Addresses` AS `Extent1` 
WHERE (`Extent1`.`AddressKey` = @p__linq__0) 
OR ((`Extent1`.`AddressKey` IS NULL) AND (@p__linq__0 IS NULL)) 

够简单。值得注意的是,AddressKey是一个带索引的varchar(255)列。

现在,这是事情。如果我将该查询粘贴到MySQL工作台并运行它(具有不同的值@p__linq__0),它甚至不会记录运行时间。它将持续时间列为0.000秒。

但是,在我的查询周围放置一个秒表,并记录执行Linq所用的时间约为0.004秒。您可能认为没什么太大差别,但这是速度至关重要的应用程序的一部分,该应用程序会将此代码运行数百万次。它很快加起来。

我对后面的upsert代码块有同样的问题。在工作台上原生运行,不到一毫秒。再次,通过EF,它需要3-4毫秒。

我是否认为这是EF MySQL插件中的弱设计?如果是这样,我可以假设我会遇到同样的问题,如果我试图改变这个通过存储过程运行或直接提交SQL与ExecuteSqlCommand()

还有什么我可以尝试清除这种性能滞后?

+0

你讲了,你有很多电话,或者只是单一的电话(大概是第一个具有额外的开销)测得的平均时间? –

+0

@IvanStoev EF记录时间是平均1k次呼叫。 SQL比较是几次单一调用。我改变了每次尝试和模仿EF在实际操作中所做的事情的关键。 –

+1

好吧,这只是一个猜测,但它可能实际上是EF查询执行/实现过程的开销,换句话说,与MySQL插件无关。您可以使用[SqlQuery](https://msdn.microsoft.com/query/dev14.query?appId=Dev14IDEF1&l=EN-US&k=k(System.Data.Entity.DbSet%601.SqlQuery); k(TargetFrameworkMoniker -.NETFramework,Version%3Dv4.6.1); k(DevLang-csharp)&rd = true),甚至是简单的'DbReader'只是想知道问题出在EF和MySQL插件上,但老实说,我认为你的需求/期望太高。 –

回答

2

运行生成的查询和LINQ表达式有很大的区别。

我们先来看什么实体框架

转换的LINQ表达式到DbExpression

这部分有时需要花更多的时间比运行查询本身。在某些情况下,如果使用多个包含,我已经看到性能不如几百毫秒。

生成查询或从缓存中把它

这可能需要一些时间来生成SQL查询的第一次,但进行呼叫会从缓存中生成的查询。

缓存使用先前生成的DbExpression创建缓存键。

执行查询

服务器延迟时间+运行查询

对象具体化

时间创建实体。通常非常快,因为您使用AsNoTracking所以需要跟踪它们。


我可能是错的,但我的猜测是,当LINQ表达式转换为DbExpression大部分时间拍摄。

您可以通过验证生成查询所用的时间而无需通过ToTraceString方法执行它来轻松验证它。小心,直接使用TraceString时,它不会计算MySQL Interceptor所花费的时间,但您至少可以粗略地了解时间。

这里是ToTraceString扩展方法(我没有测试过)的例子:Obtain ToTraceString