Ben*_*Ben 14 entity-framework entity-framework-6
尝试从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();
}
}
Run Code Online (Sandbox Code Playgroud)
当EF6生成SQL时,它会为null处理添加一些逻辑:
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))
Run Code Online (Sandbox Code Playgroud)
注意同样的linq在EF5下产生了更简单的SQL:
SELECT
[Extent1].[Id] AS [Id]
FROM [dbo].[Customers] AS [Extent1]
WHERE [Extent1].[ManagerId] = @p__linq__0
Run Code Online (Sandbox Code Playgroud)
我可以理解开发人员试图实现的要点:如果提供null作为参数,那么managerId = null的查询将不会选择任何行.我很欣赏这种关注,但99.9%的搜索逻辑是分开的:一个用例寻找where ManagerId == null,另一个搜索特定的idwhere ManagerId == managerId
问题在于性能影响很大:MS SQL不使用ManagerId上的索引并且发生表扫描.我的项目有数百个类似的搜索和数据库大小约100GB的整体性能升级到EF6减少约10.
问题是有人知道在EF6中禁用此包版并生成简单的sql的某种配置或约定吗?
编辑:
我在项目中检查了十几个类似的选择,发现:
当常量被精确指定为非null时,EF6甚至会检查null,例如:
from p in db.PtnActivations
where p.Carrier != "ALLTEL"
where p.Carrier != "ATT"
where p.Carrier != "VERIZON"
Run Code Online (Sandbox Code Playgroud)生成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)))
Run Code Online (Sandbox Code Playgroud)
没有在载体上使用我的索引.EF5版本了
( NOT (('ALLTEL' = [Extent1].[Carrier]))) AND ( NOT (('ATT' = [Extent1].[Carrier]))) AND ( NOT (('VERIZON' = [Extent1].[Carrier]) ))
Run Code Online (Sandbox Code Playgroud)
利用它.
注意条件('ALLTEL' = [Extent1].[Carrier]) AND ([Extent1].[Carrier] IS NOT NULL).第二部分总是假的,但添加这部分会放弃索引.
我常规导入大约170万条记录(通常大约需要30分钟),持续3小时,进度大约为30%.
Paw*_*wel 14
组
db.Configuration.UseDatabaseNullSemantics = true;
Run Code Online (Sandbox Code Playgroud)
获得你在EF5中的行为.这个工作项描述了和之间的区别true,false是什么和应该帮助你决定你是否对旧的行为感到满意.
| 归档时间: |
|
| 查看次数: |
2240 次 |
| 最近记录: |