You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

EF Core中LINQ的Contains未转成IN导致SQLite查询过慢如何解决

问题原因

EF Core默认对可空类型的相等判断会自动补充OR 两边都为NULL的兼容逻辑,加上当前版本的EF Core对Contains的子查询翻译做了降级处理,最终生成了带额外NULL判断的EXISTS关联查询,导致索引无法命中,查询效率骤降。

解决方案

方案1:修改LINQ写法强制非空(推荐)

你的子查询已经过滤了JobID != null,可以显式告知EF Core查询结果不存在NULL值,避免生成额外兼容逻辑:

// 先查最近3个非空JobID,显式取可空类型的Value
var recentJobIds = ServicesData
    .Where(y => y.JobID != null)
    .GroupBy(y => y.JobID)
    .OrderByDescending(y => y.Max(z => z.Time))
    .Select(y => y.Key.Value)
    .Take(3);

// 主查询也显式用JobID的Value匹配
var result = ServicesData
    .Where(x => recentJobIds.Contains(x.JobID.Value))
    .OrderBy(x => x.Time)
    .ToList();

修改后EF Core会直接生成和原生写法一致的IN运算符查询,性能和原生SQL基本持平。

方案2:关闭EF Core空值兼容逻辑

如果你的项目不需要兼容C#和SQL的空值判断差异,可以在DbContext配置中关闭该行为:

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
    optionsBuilder
        .UseSqlite("你的数据库连接字符串")
        .UseRelationalNulls(); // 启用数据库原生空值比较规则,不生成额外NULL判断逻辑
}

配置后你原来的LINQ写法就会直接生成IN语法的SQL,无需修改业务代码。

方案3:直接执行原生SQL

对性能要求极高的场景可以直接在EF Core中执行手写的原生SQL:

var result = ServicesData
    .FromSqlRaw(@"SELECT * FROM ServicesData
WHERE JobID IN (
  SELECT JobID
  FROM ServicesData
  WHERE JobID IS NOT NULL
  GROUP BY JobID
  ORDER BY MAX(Time) DESC LIMIT 3
)
ORDER BY Time;")
    .ToList();

该方案性能和直接在SQLite中执行查询完全一致。

内容的提问来源于stack exchange,提问作者kofifus

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.04 14:27:02