gpt4 book ai didi

entity-framework - EF6 SQL 生成

转载 作者:行者123 更新时间:2023-12-03 22:23:25 25 4
gpt4 key购买 nike

在尝试从 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 时,它会添加一些用于 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))

注意同样的 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 , 另一个搜索特定 id where ManagerId == managerId
问题在于性能影响很大:MS SQL 不使用 ManagerId 上的索引,并且发生了表扫描。我的项目有数百个类似的搜索,在升级到 EF6 后,数据库大小约为 100GB,整体性能减少了大约 10 个。

问题是有人知道在 EF6 中禁用此障碍并生成简单 sql 的某种配置或约定吗?

编辑:

我在我的项目中检查了十几个类似的选择,发现:
  • 在某些情况下,SQL SERVER 确实使用为字段 I 指定的索引
    搜索。即使在这种情况下也有轻微的性能损失:它
    两次使用索引:第一次查找我在中指定的值
    参数,第二次寻找空值
  • 当常量被精确指定为非空时,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) .第二部分是 总是 false,但添加此部分会放弃索引。

    我的大约 170 万条记录(通常需要大约 30 分钟)的例行导入持续了 3 小时,进度约为 30%。

    最佳答案


    db.Configuration.UseDatabaseNullSemantics = true;

    获得您在 EF5 中的行为。此 workitem描述了 true 之间的区别和 false是并且应该帮助您决定您是否接受旧行为。

    关于entity-framework - EF6 SQL 生成 <where 可空列等于>,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19672799/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com