尝试从EF5升级到EF6时,我遇到了由可空列搜索表格的巨大性能差距。这是一个示例:
public class Customer
{
public int Id { get; set; }
public int? ManagerId { get; set; }
//public virtual Manager Manager { get; set; }
}
public class MyContext : DbContext
{
public MyContext(string connstring): base(connstring){}
public DbSet<Customer> Customers { get; set; }
}
class Program
{
static void Main(string[] args)
{
var db = new MyContext("CONNSTRING");
var managerId = 1234;
var q = from b in db.Customers
where b.ManagerId == managerId
select b.Id;
var s = q.ToString();
}
}
EF6生成SQL时,会添加一些用于空值处理的逻辑:
SELECT
[Extent1].[Id] AS [Id]
FROM [dbo].[Customers] AS [Extent1]
WHERE (([Extent1].[ManagerId] = @p__linq__0)
AND ( NOT ([Extent1].[ManagerId] IS NULL OR @p__linq__0 IS NULL)))
OR (([Extent1].[ManagerId] IS NULL) AND (@p__linq__0 IS NULL))
注意,相同的linq在EF5下产生了更简单的SQL:
SELECT
[Extent1].[Id] AS [Id]
FROM [dbo].[Customers] AS [Extent1]
WHERE [Extent1].[ManagerId] = @p__linq__0
我可以理解开发人员试图达到的目的:如果提供null作为参数,则managerId = null的查询将不会选择任何行。我很感谢您的关心,但是99.9%的搜索逻辑是分开的:一个用例寻找where ManagerId == null
,另一个寻找特定IDwhere ManagerId == managerId
问题在于对性能的影响很大:MS SQL不对ManagerId使用索引,并且发生表扫描。我的项目有数百个类似的搜索,并且在升级到EF6后,数据库大小的整体性能约为100GB,大约减少了10%。
问题是,有人知道某种配置或约定来禁用EF6中的此障碍并生成简单的sql吗?
编辑:
我检查了项目中的十几个类似选择,发现:
当常量被精确地指定为非空值时,EF6甚至检查空值,例如:
from p in db.PtnActivations
where p.Carrier != "ALLTEL"
where p.Carrier != "ATT"
where p.Carrier != "VERIZON"
生成SQL
WHERE ( NOT (('ALLTEL' = [Extent1].[Carrier]) AND ([Extent1].[Carrier] IS NOT NULL))) AND ( NOT (('ATT' = [Extent1].[Carrier]) AND ([Extent1].[Carrier] IS NOT NULL))) AND ( NOT (('VERIZON' = [Extent1].[Carrier]) AND ([Extent1].[Carrier] IS NOT NULL)))
没有利用我在载体上的索引。EF5版本有
( NOT (('ALLTEL' = [Extent1].[Carrier]))) AND ( NOT (('ATT' = [Extent1].[Carrier]))) AND ( NOT (('VERIZON' = [Extent1].[Carrier]) ))
利用它。
注意条件('ALLTEL' = [Extent1].[Carrier]) AND ([Extent1].[Carrier] IS NOT NULL)
。第二部分总是错误的,但是添加这部分将放弃索引。
我的常规导入大约170万条记录(通常需要大约30分钟)最多需要3个小时,并且进度约为30%。
组
db.Configuration.UseDatabaseNullSemantics = true;
获得您在EF5中的行为。此工作项描述了和之间的区别true
,false
并应帮助您确定您是否同意旧的行为。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句